Patch 8.1.1355
Problem: Obvious mistakes are accepted as valid expressions.
Solution: Be more strict about parsing numbers. (Yasuhiro Matsumoto,
closes #3981)
Files: src/charset.c, src/eval.c, src/evalfunc.c, src/ex_cmds.c,
src/ex_getln.c, src/json.c, src/misc2.c, src/ops.c, src/option.c,
src/proto/charset.pro, src/testdir/test_expr.vim,
src/testdir/test_json.vim
*** ../vim-8.1.1354/src/charset.c 2019-03-21 21:45:30.883282076 +0100
--- src/charset.c 2019-05-19 19:02:56.822368539 +0200
***************
*** 1776,1800 ****
* If "what" contains STR2NR_HEX recognize hex numbers
* If "what" contains STR2NR_FORCE always assume bin/oct/hex.
* If maxlen > 0, check at a maximum maxlen chars.
*/
void
vim_str2nr(
char_u *start,
! int *prep, /* return: type of number 0 =
decimal, 'x'
! or 'X' is hex, '0' = octal, 'b' or 'B'
! is bin */
! int *len, /* return: detected length of
number */
! int what, /* what numbers to recognize */
! varnumber_T *nptr, /* return: signed result */
! uvarnumber_T *unptr, /* return: unsigned result */
! int maxlen) /* max length of string to check */
{
char_u *ptr = start;
! int pre = 0; /* default is decimal */
int negative = FALSE;
uvarnumber_T un = 0;
int n;
if (ptr[0] == '-')
{
negative = TRUE;
--- 1776,1805 ----
* If "what" contains STR2NR_HEX recognize hex numbers
* If "what" contains STR2NR_FORCE always assume bin/oct/hex.
* If maxlen > 0, check at a maximum maxlen chars.
+ * If strict is TRUE, check the number strictly. return *len = 0 if fail.
*/
void
vim_str2nr(
char_u *start,
! int *prep, // return: type of number 0 =
decimal, 'x'
! // or 'X' is hex, '0' = octal, 'b' or 'B'
! // is bin
! int *len, // return: detected length of number
! int what, // what numbers to recognize
! 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
int negative = FALSE;
uvarnumber_T un = 0;
int n;
+ if (len != NULL)
+ *len = 0;
+
if (ptr[0] == '-')
{
negative = TRUE;
***************
*** 1836,1844 ****
}
}
! /*
! * Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
! */
n = 1;
if (pre == 'B' || pre == 'b' || what == STR2NR_BIN + STR2NR_FORCE)
{
--- 1841,1847 ----
}
}
! // Do the conversion manually to avoid sscanf() quirks.
n = 1;
if (pre == 'B' || pre == 'b' || what == STR2NR_BIN + STR2NR_FORCE)
{
***************
*** 1907,1912 ****
--- 1910,1919 ----
break;
}
}
+ // Check for an alpha-numeric character immediately following, that is
+ // most likely a typo.
+ if (strict && n - 1 != maxlen && ASCII_ISALNUM(*ptr))
+ return;
if (prep != NULL)
*prep = pre;
*** ../vim-8.1.1354/src/eval.c 2019-05-19 18:41:23.262148495 +0200
--- src/eval.c 2019-05-19 18:53:32.114127645 +0200
***************
*** 4453,4459 ****
else
{
// decimal, hex or octal number
! vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0);
*arg += len;
if (evaluate)
{
--- 4453,4465 ----
else
{
// decimal, hex or octal number
! vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, TRUE);
! if (len == 0)
! {
! semsg(_(e_invexpr2), *arg);
! ret = FAIL;
! break;
! }
*arg += len;
if (evaluate)
{
***************
*** 7460,7466 ****
case VAR_STRING:
if (varp->vval.v_string != NULL)
vim_str2nr(varp->vval.v_string, NULL, NULL,
! STR2NR_ALL, &n, NULL, 0);
return n;
case VAR_LIST:
emsg(_("E745: Using a List as a Number"));
--- 7466,7472 ----
case VAR_STRING:
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(_("E745: Using a List as a Number"));
*** ../vim-8.1.1354/src/evalfunc.c 2019-05-19 15:27:09.394109547 +0200
--- src/evalfunc.c 2019-05-19 18:53:32.118127617 +0200
***************
*** 13199,13205 ****
case 16: what = STR2NR_HEX + STR2NR_FORCE; break;
default: what = 0;
}
! vim_str2nr(p, NULL, NULL, what, &n, NULL, 0);
if (isneg)
rettv->vval.v_number = -n;
else
--- 13199,13206 ----
case 16: what = STR2NR_HEX + STR2NR_FORCE; break;
default: what = 0;
}
! vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, FALSE);
! // Text after the number is silently ignored.
if (isneg)
rettv->vval.v_number = -n;
else
*** ../vim-8.1.1354/src/ex_cmds.c 2019-05-19 15:19:53.820445439 +0200
--- src/ex_cmds.c 2019-05-19 18:53:32.118127617 +0200
***************
*** 558,564 ****
{
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);
}
}
#ifdef FEAT_FLOAT
--- 558,565 ----
{
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);
}
}
#ifdef FEAT_FLOAT
*** ../vim-8.1.1354/src/ex_getln.c 2019-05-09 15:12:45.168723969 +0200
--- src/ex_getln.c 2019-05-19 18:53:32.118127617 +0200
***************
*** 6470,6476 ****
*str = skipwhite(*str);
if (**str == '-' || vim_isdigit(**str)) /* parse "from" part of range */
{
! vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0);
*str += len;
*num1 = (int)num;
first = TRUE;
--- 6470,6476 ----
*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;
***************
*** 6479,6485 ****
if (**str == ',') /* parse "to" part of range */
{
*str = skipwhite(*str + 1);
! vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0);
if (len > 0)
{
*num2 = (int)num;
--- 6479,6485 ----
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;
*** ../vim-8.1.1354/src/json.c 2019-04-12 21:19:01.265386241 +0200
--- src/json.c 2019-05-19 18:53:32.118127617 +0200
***************
*** 452,458 ****
nr = 0;
len = 0;
vim_str2nr(p + 2, NULL, &len,
! STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4);
p += len + 2;
if (0xd800 <= nr && nr <= 0xdfff
&& (int)(reader->js_end - p) >= 6
--- 452,463 ----
nr = 0;
len = 0;
vim_str2nr(p + 2, NULL, &len,
! STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4, TRUE);
! if (len == 0)
! {
! ga_clear(&ga);
! return FAIL;
! }
p += len + 2;
if (0xd800 <= nr && nr <= 0xdfff
&& (int)(reader->js_end - p) >= 6
***************
*** 463,469 ****
/* decode surrogate pair: \ud812\u3456 */
len = 0;
vim_str2nr(p + 2, NULL, &len,
! STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4);
if (0xdc00 <= nr2 && nr2 <= 0xdfff)
{
p += len + 2;
--- 468,479 ----
/* decode surrogate pair: \ud812\u3456 */
len = 0;
vim_str2nr(p + 2, NULL, &len,
! STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4, TRUE);
! if (len == 0)
! {
! ga_clear(&ga);
! return FAIL;
! }
if (0xdc00 <= nr2 && nr2 <= 0xdfff)
{
p += len + 2;
***************
*** 783,789 ****
vim_str2nr(reader->js_buf + reader->js_used,
NULL, &len, 0, /* what */
! &nr, NULL, 0);
if (cur_item != NULL)
{
cur_item->v_type = VAR_NUMBER;
--- 793,805 ----
vim_str2nr(reader->js_buf + reader->js_used,
NULL, &len, 0, /* what */
! &nr, NULL, 0, TRUE);
! if (len == 0)
! {
! emsg(_(e_invarg));
! retval = FAIL;
! goto theend;
! }
if (cur_item != NULL)
{
cur_item->v_type = VAR_NUMBER;
*** ../vim-8.1.1354/src/misc2.c 2019-05-09 15:12:45.172723940 +0200
--- src/misc2.c 2019-05-19 18:53:32.118127617 +0200
***************
*** 2832,2838 ****
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);
bp += l + 5;
break;
}
--- 2832,2843 ----
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_invarg));
! return 0;
! }
bp += l + 5;
break;
}
***************
*** 2864,2870 ****
&& VIM_ISDIGIT(last_dash[6]))
{
/* <Char-123> or <Char-033> or <Char-0x33> */
! vim_str2nr(last_dash + 6, NULL, NULL, STR2NR_ALL, NULL, &n, 0);
key = (int)n;
}
else
--- 2869,2880 ----
&& VIM_ISDIGIT(last_dash[6]))
{
/* <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_invarg));
! return 0;
! }
key = (int)n;
}
else
*** ../vim-8.1.1354/src/ops.c 2019-05-19 15:19:53.824445415 +0200
--- src/ops.c 2019-05-19 18:53:32.122127587 +0200
***************
*** 5794,5800 ****
0 + (dobin ? STR2NR_BIN : 0)
+ (dooct ? STR2NR_OCT : 0)
+ (dohex ? STR2NR_HEX : 0),
! NULL, &n, maxlen);
/* ignore leading '-' for hex and octal and bin numbers */
if (pre && negative)
--- 5794,5800 ----
0 + (dobin ? STR2NR_BIN : 0)
+ (dooct ? STR2NR_OCT : 0)
+ (dohex ? STR2NR_HEX : 0),
! NULL, &n, maxlen, FALSE);
/* ignore leading '-' for hex and octal and bin numbers */
if (pre && negative)
*** ../vim-8.1.1354/src/option.c 2019-05-09 15:12:45.176723907 +0200
--- src/option.c 2019-05-19 18:53:32.122127587 +0200
***************
*** 4762,4771 ****
/* Allow negative (for 'undolevels'), octal and
* hex numbers. */
vim_str2nr(arg, NULL, &i, STR2NR_ALL,
! &value, NULL, 0);
! if (arg[i] != NUL && !VIM_ISWHITE(arg[i]))
{
! errmsg = e_invarg;
goto skip;
}
}
--- 4762,4771 ----
/* 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 = N_("E521: Number required after =");
goto skip;
}
}
*** ../vim-8.1.1354/src/proto/charset.pro 2018-05-17 13:52:29.000000000
+0200
--- src/proto/charset.pro 2019-05-19 18:53:32.122127587 +0200
***************
*** 54,60 ****
char_u *skiptowhite_esc(char_u *p);
long getdigits(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 hex2nr(int c);
int hexhex2nr(char_u *p);
int rem_backslash(char_u *str);
--- 54,60 ----
char_u *skiptowhite_esc(char_u *p);
long getdigits(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);
*** ../vim-8.1.1354/src/testdir/test_expr.vim 2018-12-15 16:08:52.998468517
+0100
--- src/testdir/test_expr.vim 2019-05-19 18:57:21.312514000 +0200
***************
*** 512,514 ****
--- 512,525 ----
call assert_equal('b', 'a'[4:0] . 'b')
call assert_equal('b', 'b' . 'a'[4:0])
endfunc
+
+ func Test_broken_number()
+ let X = 'bad'
+ call assert_fails('echo 1X', 'E15:')
+ call assert_fails('echo 0b1X', 'E15:')
+ call assert_fails('echo 0b12', 'E15:')
+ call assert_fails('echo 0x1X', 'E15:')
+ call assert_fails('echo 011X', 'E15:')
+ call assert_equal(2, str2nr('2a'))
+ call assert_fails('inoremap <Char-0b1z> b', 'E474:')
+ endfunc
*** ../vim-8.1.1354/src/testdir/test_json.vim 2019-04-12 21:19:01.265386241
+0200
--- src/testdir/test_json.vim 2019-05-19 18:53:32.122127587 +0200
***************
*** 176,181 ****
--- 176,185 ----
call assert_fails('call json_decode("{{}:42}")', "E474:")
call assert_fails('call json_decode("{[]:42}")', "E474:")
+
+ call assert_fails('call json_decode("\"\\u111Z\"")', 'E474:')
+ call assert_equal('[😂]', json_decode('"[\uD83D\uDE02]"'))
+ call assert_equal('a😂b', json_decode('"a\uD83D\uDE02b"'))
endfunc
let s:jsl5 = '[7,,,]'
*** ../vim-8.1.1354/src/version.c 2019-05-19 18:41:23.262148495 +0200
--- src/version.c 2019-05-19 18:56:01.189060580 +0200
***************
*** 769,770 ****
--- 769,772 ----
{ /* Add new patch number below this line */
+ /**/
+ 1355,
/**/
--
Bad fashion can discourage normal people from interacting with the engineer
and talking about the cute things their children do.
(Scott Adams - The Dilbert principle)
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ 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/201905191759.x4JHxp2f027745%40masaka.moolenaar.net.
For more options, visit https://groups.google.com/d/optout.