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
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;
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;
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;
|| (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;
{
// avoid ubsan error for overflow
if (un > VARNUM_MAX)
+ {
*nptr = VARNUM_MIN;
+ if (overflow != NULL)
+ *overflow = TRUE;
+ }
else
*nptr = -(varnumber_T)un;
}
{
// prevent a large unsigned number to become negative
if (un > VARNUM_MAX)
+ {
un = VARNUM_MAX;
+ if (overflow != NULL)
+ *overflow = TRUE;
+ }
*nptr = (varnumber_T)un;
}
}
if (sort_nr || sort_flt)
{
- // Make sure vim_str2nr doesn't read any digits past the end
+ // Make sure vim_str2nr() doesn't read any digits past the end
// of the match, by temporarily terminating the string there
s2 = s + end_col;
c = *s2;
nrs[lnum - eap->line1].st_u.num.is_number = TRUE;
vim_str2nr(s, NULL, NULL, sort_what,
&nrs[lnum - eap->line1].st_u.num.value,
- NULL, 0, FALSE);
+ NULL, 0, FALSE, NULL);
}
}
else
*str = skipwhite(*str);
if (**str == '-' || vim_isdigit(**str)) // parse "from" part of range
{
- vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE);
+ vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE, NULL);
*str += len;
*num1 = (int)num;
first = TRUE;
if (**str == ',') // parse "to" part of range
{
*str = skipwhite(*str + 1);
- vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE);
+ vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE, NULL);
if (len > 0)
{
*num2 = (int)num;
nr = 0;
len = 0;
vim_str2nr(p + 2, NULL, &len,
- STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4, TRUE);
+ STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4, TRUE, NULL);
if (len == 0)
{
if (res != NULL)
// decode surrogate pair: \ud812\u3456
len = 0;
- vim_str2nr(p + 2, NULL, &len,
- STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4, TRUE);
+ vim_str2nr(p + 2, NULL, &len, STR2NR_HEX + STR2NR_FORCE,
+ &nr2, NULL, 4, TRUE, NULL);
if (len == 0)
{
if (res != NULL)
vim_str2nr(reader->js_buf + reader->js_used,
NULL, &len, 0, // what
- &nr, NULL, 0, TRUE);
+ &nr, NULL, 0, TRUE, NULL);
if (len == 0)
{
semsg(_(e_json_decode_error_at_str), p);
bp += 3; // skip t_xx, xx may be '-' or '>'
else if (STRNICMP(bp, "char-", 5) == 0)
{
- vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, TRUE);
+ vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, TRUE, NULL);
if (l == 0)
{
emsg(_(e_invalid_argument));
{
// <Char-123> or <Char-033> or <Char-0x33>
vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL,
- &n, 0, TRUE);
+ &n, 0, TRUE, NULL);
if (l == 0)
{
emsg(_(e_invalid_argument));
? (int)STRLEN(ptr) - col
: length);
+ int overflow = FALSE;
vim_str2nr(ptr + col, &pre, &length,
0 + (do_bin ? STR2NR_BIN : 0)
+ (do_oct ? STR2NR_OCT : 0)
+ (do_hex ? STR2NR_HEX : 0),
- NULL, &n, maxlen, FALSE);
+ NULL, &n, maxlen, FALSE, &overflow);
// ignore leading '-' for hex and octal and bin numbers
if (pre && negative)
subtract ^= TRUE;
oldn = n;
- if (subtract)
- n -= (uvarnumber_T)Prenum1;
- else
- n += (uvarnumber_T)Prenum1;
+ if (!overflow) // if number is too big don't add/subtract
+ {
+ if (subtract)
+ n -= (uvarnumber_T)Prenum1;
+ else
+ n += (uvarnumber_T)Prenum1;
+ }
+
// handle wraparound for decimal numbers
if (!pre)
{
else if (*arg == '-' || VIM_ISDIGIT(*arg))
{
// Allow negative (for 'undolevels'), octal and hex numbers.
- vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, TRUE);
+ vim_str2nr(arg, NULL, &i, STR2NR_ALL, &value, NULL, 0, TRUE, NULL);
if (i == 0 || (arg[i] != NUL && !VIM_ISWHITE(arg[i])))
{
errmsg = e_number_required_after_equal;
long getdigits(char_u **pp);
long getdigits_quoted(char_u **pp);
int vim_isblankline(char_u *lbuf);
-void vim_str2nr(char_u *start, int *prep, int *len, int what, varnumber_T *nptr, uvarnumber_T *unptr, int maxlen, int strict);
+void vim_str2nr(char_u *start, int *prep, int *len, int what, varnumber_T *nptr, uvarnumber_T *unptr, int maxlen, int strict, int *overflow);
int hex2nr(int c);
int hexhex2nr(char_u *p);
int rem_backslash(char_u *str);
case 8: what |= STR2NR_OCT + STR2NR_OOCT + STR2NR_FORCE; break;
case 16: what |= STR2NR_HEX + STR2NR_FORCE; break;
}
- vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, FALSE);
+ vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, FALSE, NULL);
// Text after the number is silently ignored.
if (isneg)
rettv->vval.v_number = -n;
set nrformats-=unsigned
endfunc
+func Test_in_decrement_large_number()
+ " NOTE: 18446744073709551616 == 2^64
+ call setline(1, '18446744073709551616')
+ exec "norm! gg0\<C-X>"
+ call assert_equal('18446744073709551615', getline(1))
+
+ exec "norm! gg0\<C-X>"
+ call assert_equal('18446744073709551614', getline(1))
+
+ exec "norm! gg0\<C-A>"
+ call assert_equal('18446744073709551615', getline(1))
+
+ exec "norm! gg0\<C-A>"
+ call assert_equal('-18446744073709551615', getline(1))
+endfunc
+
func Test_normal_increment_with_virtualedit()
set virtualedit=all
}
if (varp->vval.v_string != NULL)
vim_str2nr(varp->vval.v_string, NULL, NULL,
- STR2NR_ALL, &n, NULL, 0, FALSE);
+ STR2NR_ALL, &n, NULL, 0, FALSE, NULL);
return n;
case VAR_LIST:
emsg(_(e_using_list_as_number));
// decimal, hex or octal number
vim_str2nr(*arg, NULL, &len, skip_quotes
? STR2NR_NO_OCT + STR2NR_QUOTE
- : STR2NR_ALL, &n, NULL, 0, TRUE);
+ : STR2NR_ALL, &n, NULL, 0, TRUE, NULL);
if (len == 0)
{
if (evaluate)
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1380,
/**/
1379,
/**/