Patch 9.0.1380
Problem: CTRL-X on 2**64 subtracts two. (James McCoy)
Solution: Correct computation for large number. (closes #12103)
Files: src/charset.c, src/proto/charset.pro, src/ex_cmds.c,
src/ex_getln.c, src/json.c, src/misc2.c, src/ops.c, src/option.c,
src/strings.c, src/typval.c, src/testdir/test_increment.vim
*** ../vim-9.0.1379/src/charset.c 2023-02-21 14:27:34.512360384 +0000
--- src/charset.c 2023-03-04 20:39:35.476205644 +0000
***************
*** 2138,2144 ****
varnumber_T *nptr, // return: signed result
uvarnumber_T *unptr, // return: unsigned result
int maxlen, // max length of string to check
! int strict) // check strictly
{
char_u *ptr = start;
int pre = 0; // default is decimal
--- 2138,2145 ----
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 *overflow) // when not NULL set to TRUE for
overflow
{
char_u *ptr = start;
int pre = 0; // default is decimal
***************
*** 2209,2215 ****
--- 2210,2220 ----
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,2240 ****
--- 2239,2249 ----
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,2264 ****
--- 2267,2277 ----
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,2288 ****
--- 2295,2305 ----
|| (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,2316 ****
--- 2327,2337 ----
{
// avoid ubsan error for overflow
if (un > VARNUM_MAX)
+ {
*nptr = VARNUM_MIN;
+ if (overflow != NULL)
+ *overflow = TRUE;
+ }
else
*nptr = -(varnumber_T)un;
}
***************
*** 2318,2324 ****
--- 2339,2349 ----
{
// prevent a large unsigned number to become negative
if (un > VARNUM_MAX)
+ {
un = VARNUM_MAX;
+ if (overflow != NULL)
+ *overflow = TRUE;
+ }
*nptr = (varnumber_T)un;
}
}
*** ../vim-9.0.1379/src/proto/charset.pro 2023-02-16 15:03:08.501667452
+0000
--- src/proto/charset.pro 2023-03-04 20:44:54.984494997 +0000
***************
*** 64,70 ****
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);
int hex2nr(int c);
int hexhex2nr(char_u *p);
int rem_backslash(char_u *str);
--- 64,70 ----
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, int *overflow);
int hex2nr(int c);
int hexhex2nr(char_u *p);
int rem_backslash(char_u *str);
*** ../vim-9.0.1379/src/ex_cmds.c 2023-02-20 12:16:33.328269404 +0000
--- src/ex_cmds.c 2023-03-04 20:40:53.824282930 +0000
***************
*** 511,517 ****
if (sort_nr || sort_flt)
{
! // 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;
--- 511,517 ----
if (sort_nr || sort_flt)
{
! // 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;
***************
*** 539,545 ****
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);
}
}
else
--- 539,545 ----
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);
}
}
else
*** ../vim-9.0.1379/src/ex_getln.c 2023-02-20 12:16:33.328269404 +0000
--- src/ex_getln.c 2023-03-04 20:41:05.688294226 +0000
***************
*** 4338,4344 ****
*str = skipwhite(*str);
if (**str == '-' || vim_isdigit(**str)) // parse "from" part of range
{
! vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE);
*str += len;
*num1 = (int)num;
first = TRUE;
--- 4338,4344 ----
*str = skipwhite(*str);
if (**str == '-' || vim_isdigit(**str)) // parse "from" part of range
{
! vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE, NULL);
*str += len;
*num1 = (int)num;
first = TRUE;
***************
*** 4347,4353 ****
if (**str == ',') // parse "to" part of range
{
*str = skipwhite(*str + 1);
! vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE);
if (len > 0)
{
*num2 = (int)num;
--- 4347,4353 ----
if (**str == ',') // parse "to" part of range
{
*str = skipwhite(*str + 1);
! vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE, NULL);
if (len > 0)
{
*num2 = (int)num;
*** ../vim-9.0.1379/src/json.c 2022-12-08 15:32:11.083034191 +0000
--- src/json.c 2023-03-04 20:41:39.344325712 +0000
***************
*** 540,546 ****
nr = 0;
len = 0;
vim_str2nr(p + 2, NULL, &len,
! STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4, TRUE);
if (len == 0)
{
if (res != NULL)
--- 540,546 ----
nr = 0;
len = 0;
vim_str2nr(p + 2, NULL, &len,
! STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4, TRUE,
NULL);
if (len == 0)
{
if (res != NULL)
***************
*** 556,563 ****
// decode surrogate pair: \ud812\u3456
len = 0;
! vim_str2nr(p + 2, NULL, &len,
! STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4, TRUE);
if (len == 0)
{
if (res != NULL)
--- 556,563 ----
// decode surrogate pair: \ud812\u3456
len = 0;
! vim_str2nr(p + 2, NULL, &len, STR2NR_HEX + STR2NR_FORCE,
! &nr2, NULL, 4, TRUE, NULL);
if (len == 0)
{
if (res != NULL)
***************
*** 882,888 ****
vim_str2nr(reader->js_buf + reader->js_used,
NULL, &len, 0, // what
! &nr, NULL, 0, TRUE);
if (len == 0)
{
semsg(_(e_json_decode_error_at_str), p);
--- 882,888 ----
vim_str2nr(reader->js_buf + reader->js_used,
NULL, &len, 0, // what
! &nr, NULL, 0, TRUE, NULL);
if (len == 0)
{
semsg(_(e_json_decode_error_at_str), p);
*** ../vim-9.0.1379/src/misc2.c 2023-02-11 16:15:46.140840726 +0000
--- src/misc2.c 2023-03-04 20:41:54.724339840 +0000
***************
*** 1410,1416 ****
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);
if (l == 0)
{
emsg(_(e_invalid_argument));
--- 1410,1416 ----
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, NULL);
if (l == 0)
{
emsg(_(e_invalid_argument));
***************
*** 1448,1454 ****
{
// <Char-123> or <Char-033> or <Char-0x33>
vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL,
! &n, 0, TRUE);
if (l == 0)
{
emsg(_(e_invalid_argument));
--- 1448,1454 ----
{
// <Char-123> or <Char-033> or <Char-0x33>
vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL,
! &n, 0, TRUE, NULL);
if (l == 0)
{
emsg(_(e_invalid_argument));
*** ../vim-9.0.1379/src/ops.c 2023-02-20 12:16:33.332269406 +0000
--- src/ops.c 2023-03-04 20:43:16.540412494 +0000
***************
*** 2781,2791 ****
? (int)STRLEN(ptr) - col
: length);
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);
// ignore leading '-' for hex and octal and bin numbers
if (pre && negative)
--- 2781,2792 ----
? (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, &overflow);
// ignore leading '-' for hex and octal and bin numbers
if (pre && negative)
***************
*** 2802,2811 ****
subtract ^= TRUE;
oldn = n;
! if (subtract)
! n -= (uvarnumber_T)Prenum1;
! else
! n += (uvarnumber_T)Prenum1;
// handle wraparound for decimal numbers
if (!pre)
{
--- 2803,2816 ----
subtract ^= TRUE;
oldn = n;
! 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)
{
*** ../vim-9.0.1379/src/option.c 2023-03-04 19:57:28.342671183 +0000
--- src/option.c 2023-03-04 20:43:32.100425875 +0000
***************
*** 2157,2163 ****
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);
if (i == 0 || (arg[i] != NUL && !VIM_ISWHITE(arg[i])))
{
errmsg = e_number_required_after_equal;
--- 2157,2163 ----
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, NULL);
if (i == 0 || (arg[i] != NUL && !VIM_ISWHITE(arg[i])))
{
errmsg = e_number_required_after_equal;
*** ../vim-9.0.1379/src/strings.c 2023-01-23 20:46:16.166493150 +0000
--- src/strings.c 2023-03-04 20:43:37.844430785 +0000
***************
*** 1188,1194 ****
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);
// Text after the number is silently ignored.
if (isneg)
rettv->vval.v_number = -n;
--- 1188,1194 ----
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, NULL);
// Text after the number is silently ignored.
if (isneg)
rettv->vval.v_number = -n;
*** ../vim-9.0.1379/src/typval.c 2023-01-25 21:05:35.131042802 +0000
--- src/typval.c 2023-03-04 20:43:56.792446834 +0000
***************
*** 217,223 ****
}
if (varp->vval.v_string != NULL)
vim_str2nr(varp->vval.v_string, NULL, NULL,
! STR2NR_ALL, &n, NULL, 0, FALSE);
return n;
case VAR_LIST:
emsg(_(e_using_list_as_number));
--- 217,223 ----
}
if (varp->vval.v_string != NULL)
vim_str2nr(varp->vval.v_string, NULL, NULL,
! STR2NR_ALL, &n, NULL, 0, FALSE, NULL);
return n;
case VAR_LIST:
emsg(_(e_using_list_as_number));
***************
*** 2230,2236 ****
// decimal, hex or octal number
vim_str2nr(*arg, NULL, &len, skip_quotes
? STR2NR_NO_OCT + STR2NR_QUOTE
! : STR2NR_ALL, &n, NULL, 0, TRUE);
if (len == 0)
{
if (evaluate)
--- 2230,2236 ----
// decimal, hex or octal number
vim_str2nr(*arg, NULL, &len, skip_quotes
? STR2NR_NO_OCT + STR2NR_QUOTE
! : STR2NR_ALL, &n, NULL, 0, TRUE, NULL);
if (len == 0)
{
if (evaluate)
*** ../vim-9.0.1379/src/testdir/test_increment.vim 2023-01-28
19:18:56.729720605 +0000
--- src/testdir/test_increment.vim 2023-03-04 20:46:49.696585531 +0000
***************
*** 840,845 ****
--- 840,861 ----
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
*** ../vim-9.0.1379/src/version.c 2023-03-04 19:57:28.342671183 +0000
--- src/version.c 2023-03-04 20:20:43.225852411 +0000
***************
*** 697,698 ****
--- 697,700 ----
{ /* Add new patch number below this line */
+ /**/
+ 1380,
/**/
--
hundred-and-one symptoms of being an internet addict:
224. You set up your own Web page. You set up a Web page for each
of your kids... and your pets.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/vim_dev/20230304204805.4C3DE1C0419%40moolenaar.net.