patch 9.0.1380: CTRL-X on 2**64 subtracts two
Problem: CTRL-X on 2**64 subtracts two. (James McCoy)
Solution: Correct computation for large number. (closes #12103)
diff --git a/src/charset.c b/src/charset.c
index 826a768..6b2790f 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -2138,7 +2138,8 @@
varnumber_T *nptr, // return: signed result
uvarnumber_T *unptr, // return: unsigned result
int maxlen, // max length of string to check
- int strict) // check strictly
+ int strict, // check strictly
+ int *overflow) // when not NULL set to TRUE for overflow
{
char_u *ptr = start;
int pre = 0; // default is decimal
@@ -2209,7 +2210,11 @@
if (un <= UVARNUM_MAX / 2)
un = 2 * un + (uvarnumber_T)(*ptr - '0');
else
+ {
un = UVARNUM_MAX;
+ if (overflow != NULL)
+ *overflow = TRUE;
+ }
++ptr;
if (n++ == maxlen)
break;
@@ -2234,7 +2239,11 @@
if (un <= UVARNUM_MAX / 8)
un = 8 * un + (uvarnumber_T)(*ptr - '0');
else
+ {
un = UVARNUM_MAX;
+ if (overflow != NULL)
+ *overflow = TRUE;
+ }
++ptr;
if (n++ == maxlen)
break;
@@ -2258,7 +2267,11 @@
if (un <= UVARNUM_MAX / 16)
un = 16 * un + (uvarnumber_T)hex2nr(*ptr);
else
+ {
un = UVARNUM_MAX;
+ if (overflow != NULL)
+ *overflow = TRUE;
+ }
++ptr;
if (n++ == maxlen)
break;
@@ -2282,7 +2295,11 @@
|| (un == UVARNUM_MAX / 10 && digit <= UVARNUM_MAX % 10))
un = 10 * un + digit;
else
+ {
un = UVARNUM_MAX;
+ if (overflow != NULL)
+ *overflow = TRUE;
+ }
++ptr;
if (n++ == maxlen)
break;
@@ -2310,7 +2327,11 @@
{
// avoid ubsan error for overflow
if (un > VARNUM_MAX)
+ {
*nptr = VARNUM_MIN;
+ if (overflow != NULL)
+ *overflow = TRUE;
+ }
else
*nptr = -(varnumber_T)un;
}
@@ -2318,7 +2339,11 @@
{
// prevent a large unsigned number to become negative
if (un > VARNUM_MAX)
+ {
un = VARNUM_MAX;
+ if (overflow != NULL)
+ *overflow = TRUE;
+ }
*nptr = (varnumber_T)un;
}
}