patch 9.1.1258: regexp: max \U and \%U value is limited by INT_MAX
Problem: regexp: max \U and \%U value is limited by INT_MAX but gives a
confusing error message (related: v8.1.0985).
Solution: give a better error message when the value reaches INT_MAX
When searching Vim allows to get up to 8 hex characters using the /\V
and /\%V regex atoms. However, when using "/\UFFFFFFFF" the code point is
already above what an integer variable can hold, which is 2,147,483,647.
Since patch v8.1.0985, Vim already limited the max codepoint to INT_MAX
(otherwise it caused a crash in the nfa regex engine), but instead of
error'ing out it silently fell back to parse the number as a backslash
value and not as a codepoint value and as such this "/[\UFFFFFFFF]" will
happily find a "\" or an literal "F". And this "/[\d127-\UFFFFFFFF]"
will error out as "reverse range in character class).
Interestingly, the max Unicode codepoint value is U+10FFFF which still
fits into an ordinary integer value, which means, that we don't even
need to parse 8 hex characters, but 6 should have been enough.
However, let's not limit Vim to search for only max 6 hex characters
(which would be a backward incompatible change), but instead allow all 8
characters and only if the codepoint reaches INT_MAX, give a more
precise error message (about what the max unicode codepoint value is).
This allows to search for "[\U7FFFFFFE]" (will likely return "E486
Pattern not found") and "[/\U7FFFFFF]" now errors "E1517: Value too
large, max Unicode codepoint is U+10FFFF".
While this change is straight forward on architectures where long is 8
bytes, this is not so simple on Windows or 32bit architectures where long
is 4 bytes (and therefore the test fails there). To account for that,
let's make use of the vimlong_T number type and make a few corresponding
changes in the regex engine code and cast the value to the expected data
type. This however may not work correctly on systems that doesn't have
the long long datatype (e.g. OpenVMS) and probably the test will fail
there.
fixes: #16949
closes: #16994
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/regexp.c b/src/regexp.c
index ea6079b..32a721f 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -427,9 +427,9 @@
static int peekchr(void);
static void skipchr(void);
static void ungetchr(void);
-static long gethexchrs(int maxinputlen);
+static vimlong_T gethexchrs(int maxinputlen);
static long getoctchrs(void);
-static long getdecchrs(void);
+static vimlong_T getdecchrs(void);
static int coll_get_char(void);
static int prog_magic_wrong(void);
static int cstrncmp(char_u *s1, char_u *s2, int *n);
@@ -979,7 +979,7 @@
* The parameter controls the maximum number of input characters. This will be
* 2 when reading a \%x20 sequence and 4 when reading a \%u20AC sequence.
*/
- static long
+ static vimlong_T
gethexchrs(int maxinputlen)
{
long_u nr = 0;
@@ -998,14 +998,14 @@
if (i == 0)
return -1;
- return (long)nr;
+ return nr;
}
/*
* Get and return the value of the decimal string immediately after the
* current position. Return -1 for invalid. Consumes all digits.
*/
- static long
+ static vimlong_T
getdecchrs(void)
{
long_u nr = 0;
@@ -1025,7 +1025,7 @@
if (i == 0)
return -1;
- return (long)nr;
+ return nr;
}
/*