Problem: Wrong Ex command executed when :g uses '?' as delimiter and
pattern contains escaped '?'.
Solution: Don't use "*newp" when it's not allocated (zeertzjq).
closes: #14837
Signed-off-by: zeertzjq <zeertzjq@outlook.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: too many strlen() calls in the regexp engine
Solution: refactor code to retrieve strlen differently, make use
of bsearch() for getting the character class
(John Marriott)
closes: #14648
Signed-off-by: John Marriott <basilisk@internode.on.net>
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: Patch 9.1.0296 causes too many issues
(Tony Mechelynck, @chdiza, CI)
Solution: Back out the change for now
Revert "patch 9.1.0296: regexp: engines do not handle case-folding well"
This reverts commit 7a27c108e0509f3255ebdcb6558e896c223e4d23 it causes
issues with syntax highlighting and breaks the FreeBSD and MacOS CI. It
needs more work.
fixes: #14487
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: Regex engines do not handle case-folding well
Solution: Correctly calculate byte length of characters to skip
When the regexp engine compares two utf-8 codepoints case insensitively
it may match an adjacent character, because it assumes it can step over
as many bytes as the pattern contains.
This however is not necessarily true because of case-folding, a
multi-byte UTF-8 character can be considered equal to some single-byte
value.
Let's consider the pattern 'ſ' and the string 's'. When comparing and
ignoring case, the single character 's' matches, and since it matches
Vim will try to step over the match (by the amount of bytes of the
pattern), assuming that since it matches, the length of both strings is
the same.
However in that case, it should only step over the single byte
value 's' so by 1 byte and try to start matching after it again. So for the
backtracking engine we need to ensure:
- we try to match the correct length for the pattern and the text
- in case of a match, we step over it correctly
The same thing can happen for the NFA engine, when skipping to the next
character to test for a match. We are skipping over the regstart
pointer, however we do not consider the case that because of
case-folding we may need to adjust the number of bytes to skip over. So
this needs to be adjusted in find_match_text() as well.
A related issue turned out, when prog->match_text is actually empty. In
that case we should try to find the next match and skip this condition.
fixes: #14294closes: #14433
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: ml_get: invalid lnum when :s replaces visual selection
(@ropery)
Solution: substitute may decrement the number of lines in a buffer,
so validate, that the bottom lines of the visual selection
stays within the max buffer line
fixes: #13890closes: #13892
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: regexp cannot match combining chars in collection
Solution: Check for combining characters in regex collections for the
NFA and BT Regex Engine
Also, while at it, make debug mode work again.
fixes#10286closes: #12871
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: undefined behaviour upper/lower function ptrs
Solution: Fix UBSAN error in regexp and simplify upper/lowercase
modifier code
The implementation of \u / \U / \l / \L modifiers in the substitute
command relies on remembering the state by setting function pointers on
func_all/func_one in the code. The code signature of `fptr_T` is
supposed to return void* (due to C function signatures not being able to
return itself due to type recursion), and the definition of the
functions (e.g. to_Upper) didn't follow this rule, and so the code tries
to cast functions of different signatures, resulting in undefined
behavior error under UBSAN in Clang 17. See #12745.
We could just fix `do_Upper`/etc to just return void*, which would fix
the problem. However, these functions actually do not need to return
anything at all. It used to be the case that there was only one pointer
"func" to store the pointer, which is why the function needs to either
return itself or NULL to indicate whether it's a one time or ongoing
modification. However, c2c355df6f094cdb9e599fd395a78c14486ec697
(7.3.873) already made that obsolete by introducing `func_one` and
`func_all` to store one-time and ongoing operations separately, so these
functions don't actually need to return anything anymore because it's
implicit whether it's a one-time or ongoing operation. Simplify the code
to reflect that.
closes: #13117
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Yee Cheng Chin <ychin.git@gmail.com>
Problem: CI error on different signedness in regexp.c
(after patch 9.0.1848)
Solution: Cast strlen() call to int
Signed-off-by: Christian Brabandt <cb@256bit.org>
Problem: Evaluating "expr" options has more overhead than needed.
Solution: Use call_simple_func() for 'foldtext', 'includeexpr', 'printexpr',
"expr" of 'spellsuggest', 'diffexpr', 'patchexpr', 'balloonexpr',
'formatexpr', 'indentexpr' and 'charconvert'.
Problem: Timeout handling is not optimal.
Solution: Avoid setting timeout_flag twice. Adjust the pointer when
stopping the regexp timeout. Adjust variable name.
Problem: Search timeout is overrun with some patterns.
Solution: Check for timeout in more places. Make the flag volatile and
atomic. Use assert_inrange() to see what happened.
Problem: "vimgrep /\%v/ *" may cause a crash.
Solution: When compiling the pattern with the old engine fails, restore the
regprog of the new engine instead of leaving it NULL.
(closes#10079)
Problem: Accessing invalid memory when a regular expression checks the
Visual area while matching in a string.
Solution: Do not try matching the Visual area in a string.