mirror of
https://github.com/zoriya/vim.git
synced 2025-12-20 06:05:18 +00:00
patch 8.1.1355: obvious mistakes are accepted as valid expressions
Problem: Obvious mistakes are accepted as valid expressions.
Solution: Be more strict about parsing numbers. (Yasuhiro Matsumoto,
closes #3981)
This commit is contained in:
@@ -1776,25 +1776,30 @@ vim_isblankline(char_u *lbuf)
|
|||||||
* If "what" contains STR2NR_HEX recognize hex numbers
|
* If "what" contains STR2NR_HEX recognize hex numbers
|
||||||
* If "what" contains STR2NR_FORCE always assume bin/oct/hex.
|
* If "what" contains STR2NR_FORCE always assume bin/oct/hex.
|
||||||
* If maxlen > 0, check at a maximum maxlen chars.
|
* If maxlen > 0, check at a maximum maxlen chars.
|
||||||
|
* If strict is TRUE, check the number strictly. return *len = 0 if fail.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
vim_str2nr(
|
vim_str2nr(
|
||||||
char_u *start,
|
char_u *start,
|
||||||
int *prep, /* return: type of number 0 = decimal, 'x'
|
int *prep, // return: type of number 0 = decimal, 'x'
|
||||||
or 'X' is hex, '0' = octal, 'b' or 'B'
|
// or 'X' is hex, '0' = octal, 'b' or 'B'
|
||||||
is bin */
|
// is bin
|
||||||
int *len, /* return: detected length of number */
|
int *len, // return: detected length of number
|
||||||
int what, /* what numbers to recognize */
|
int what, // what numbers to recognize
|
||||||
varnumber_T *nptr, /* return: signed result */
|
varnumber_T *nptr, // return: signed result
|
||||||
uvarnumber_T *unptr, /* return: unsigned result */
|
uvarnumber_T *unptr, // return: unsigned result
|
||||||
int maxlen) /* max length of string to check */
|
int maxlen, // max length of string to check
|
||||||
|
int strict) // check strictly
|
||||||
{
|
{
|
||||||
char_u *ptr = start;
|
char_u *ptr = start;
|
||||||
int pre = 0; /* default is decimal */
|
int pre = 0; // default is decimal
|
||||||
int negative = FALSE;
|
int negative = FALSE;
|
||||||
uvarnumber_T un = 0;
|
uvarnumber_T un = 0;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
if (len != NULL)
|
||||||
|
*len = 0;
|
||||||
|
|
||||||
if (ptr[0] == '-')
|
if (ptr[0] == '-')
|
||||||
{
|
{
|
||||||
negative = TRUE;
|
negative = TRUE;
|
||||||
@@ -1836,9 +1841,7 @@ vim_str2nr(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Do the conversion manually to avoid sscanf() quirks.
|
||||||
* Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
|
|
||||||
*/
|
|
||||||
n = 1;
|
n = 1;
|
||||||
if (pre == 'B' || pre == 'b' || what == STR2NR_BIN + STR2NR_FORCE)
|
if (pre == 'B' || pre == 'b' || what == STR2NR_BIN + STR2NR_FORCE)
|
||||||
{
|
{
|
||||||
@@ -1907,6 +1910,10 @@ vim_str2nr(
|
|||||||
break;
|
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)
|
if (prep != NULL)
|
||||||
*prep = pre;
|
*prep = pre;
|
||||||
|
|||||||
10
src/eval.c
10
src/eval.c
@@ -4453,7 +4453,13 @@ eval7(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// decimal, hex or octal number
|
// decimal, hex or octal number
|
||||||
vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0);
|
vim_str2nr(*arg, NULL, &len, STR2NR_ALL, &n, NULL, 0, TRUE);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
semsg(_(e_invexpr2), *arg);
|
||||||
|
ret = FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
*arg += len;
|
*arg += len;
|
||||||
if (evaluate)
|
if (evaluate)
|
||||||
{
|
{
|
||||||
@@ -7460,7 +7466,7 @@ tv_get_number_chk(typval_T *varp, int *denote)
|
|||||||
case VAR_STRING:
|
case VAR_STRING:
|
||||||
if (varp->vval.v_string != NULL)
|
if (varp->vval.v_string != NULL)
|
||||||
vim_str2nr(varp->vval.v_string, NULL, NULL,
|
vim_str2nr(varp->vval.v_string, NULL, NULL,
|
||||||
STR2NR_ALL, &n, NULL, 0);
|
STR2NR_ALL, &n, NULL, 0, FALSE);
|
||||||
return n;
|
return n;
|
||||||
case VAR_LIST:
|
case VAR_LIST:
|
||||||
emsg(_("E745: Using a List as a Number"));
|
emsg(_("E745: Using a List as a Number"));
|
||||||
|
|||||||
@@ -13199,7 +13199,8 @@ f_str2nr(typval_T *argvars, typval_T *rettv)
|
|||||||
case 16: what = STR2NR_HEX + STR2NR_FORCE; break;
|
case 16: what = STR2NR_HEX + STR2NR_FORCE; break;
|
||||||
default: what = 0;
|
default: what = 0;
|
||||||
}
|
}
|
||||||
vim_str2nr(p, NULL, NULL, what, &n, NULL, 0);
|
vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, FALSE);
|
||||||
|
// Text after the number is silently ignored.
|
||||||
if (isneg)
|
if (isneg)
|
||||||
rettv->vval.v_number = -n;
|
rettv->vval.v_number = -n;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -558,7 +558,8 @@ ex_sort(exarg_T *eap)
|
|||||||
{
|
{
|
||||||
nrs[lnum - eap->line1].st_u.num.is_number = TRUE;
|
nrs[lnum - eap->line1].st_u.num.is_number = TRUE;
|
||||||
vim_str2nr(s, NULL, NULL, sort_what,
|
vim_str2nr(s, NULL, NULL, sort_what,
|
||||||
&nrs[lnum - eap->line1].st_u.num.value, NULL, 0);
|
&nrs[lnum - eap->line1].st_u.num.value,
|
||||||
|
NULL, 0, FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef FEAT_FLOAT
|
#ifdef FEAT_FLOAT
|
||||||
|
|||||||
@@ -6470,7 +6470,7 @@ get_list_range(char_u **str, int *num1, int *num2)
|
|||||||
*str = skipwhite(*str);
|
*str = skipwhite(*str);
|
||||||
if (**str == '-' || vim_isdigit(**str)) /* parse "from" part of range */
|
if (**str == '-' || vim_isdigit(**str)) /* parse "from" part of range */
|
||||||
{
|
{
|
||||||
vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0);
|
vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE);
|
||||||
*str += len;
|
*str += len;
|
||||||
*num1 = (int)num;
|
*num1 = (int)num;
|
||||||
first = TRUE;
|
first = TRUE;
|
||||||
@@ -6479,7 +6479,7 @@ get_list_range(char_u **str, int *num1, int *num2)
|
|||||||
if (**str == ',') /* parse "to" part of range */
|
if (**str == ',') /* parse "to" part of range */
|
||||||
{
|
{
|
||||||
*str = skipwhite(*str + 1);
|
*str = skipwhite(*str + 1);
|
||||||
vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0);
|
vim_str2nr(*str, NULL, &len, 0, &num, NULL, 0, FALSE);
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
{
|
{
|
||||||
*num2 = (int)num;
|
*num2 = (int)num;
|
||||||
|
|||||||
22
src/json.c
22
src/json.c
@@ -452,7 +452,12 @@ json_decode_string(js_read_T *reader, typval_T *res, int quote)
|
|||||||
nr = 0;
|
nr = 0;
|
||||||
len = 0;
|
len = 0;
|
||||||
vim_str2nr(p + 2, NULL, &len,
|
vim_str2nr(p + 2, NULL, &len,
|
||||||
STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4);
|
STR2NR_HEX + STR2NR_FORCE, &nr, NULL, 4, TRUE);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
ga_clear(&ga);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
p += len + 2;
|
p += len + 2;
|
||||||
if (0xd800 <= nr && nr <= 0xdfff
|
if (0xd800 <= nr && nr <= 0xdfff
|
||||||
&& (int)(reader->js_end - p) >= 6
|
&& (int)(reader->js_end - p) >= 6
|
||||||
@@ -463,7 +468,12 @@ json_decode_string(js_read_T *reader, typval_T *res, int quote)
|
|||||||
/* decode surrogate pair: \ud812\u3456 */
|
/* decode surrogate pair: \ud812\u3456 */
|
||||||
len = 0;
|
len = 0;
|
||||||
vim_str2nr(p + 2, NULL, &len,
|
vim_str2nr(p + 2, NULL, &len,
|
||||||
STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4);
|
STR2NR_HEX + STR2NR_FORCE, &nr2, NULL, 4, TRUE);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
ga_clear(&ga);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
if (0xdc00 <= nr2 && nr2 <= 0xdfff)
|
if (0xdc00 <= nr2 && nr2 <= 0xdfff)
|
||||||
{
|
{
|
||||||
p += len + 2;
|
p += len + 2;
|
||||||
@@ -783,7 +793,13 @@ json_decode_item(js_read_T *reader, typval_T *res, int options)
|
|||||||
|
|
||||||
vim_str2nr(reader->js_buf + reader->js_used,
|
vim_str2nr(reader->js_buf + reader->js_used,
|
||||||
NULL, &len, 0, /* what */
|
NULL, &len, 0, /* what */
|
||||||
&nr, NULL, 0);
|
&nr, NULL, 0, TRUE);
|
||||||
|
if (len == 0)
|
||||||
|
{
|
||||||
|
emsg(_(e_invarg));
|
||||||
|
retval = FAIL;
|
||||||
|
goto theend;
|
||||||
|
}
|
||||||
if (cur_item != NULL)
|
if (cur_item != NULL)
|
||||||
{
|
{
|
||||||
cur_item->v_type = VAR_NUMBER;
|
cur_item->v_type = VAR_NUMBER;
|
||||||
|
|||||||
14
src/misc2.c
14
src/misc2.c
@@ -2832,7 +2832,12 @@ find_special_key(
|
|||||||
bp += 3; /* skip t_xx, xx may be '-' or '>' */
|
bp += 3; /* skip t_xx, xx may be '-' or '>' */
|
||||||
else if (STRNICMP(bp, "char-", 5) == 0)
|
else if (STRNICMP(bp, "char-", 5) == 0)
|
||||||
{
|
{
|
||||||
vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0);
|
vim_str2nr(bp + 5, NULL, &l, STR2NR_ALL, NULL, NULL, 0, TRUE);
|
||||||
|
if (l == 0)
|
||||||
|
{
|
||||||
|
emsg(_(e_invarg));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
bp += l + 5;
|
bp += l + 5;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2864,7 +2869,12 @@ find_special_key(
|
|||||||
&& VIM_ISDIGIT(last_dash[6]))
|
&& VIM_ISDIGIT(last_dash[6]))
|
||||||
{
|
{
|
||||||
/* <Char-123> or <Char-033> or <Char-0x33> */
|
/* <Char-123> or <Char-033> or <Char-0x33> */
|
||||||
vim_str2nr(last_dash + 6, NULL, NULL, STR2NR_ALL, NULL, &n, 0);
|
vim_str2nr(last_dash + 6, NULL, &l, STR2NR_ALL, NULL, &n, 0, TRUE);
|
||||||
|
if (l == 0)
|
||||||
|
{
|
||||||
|
emsg(_(e_invarg));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
key = (int)n;
|
key = (int)n;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -5794,7 +5794,7 @@ do_addsub(
|
|||||||
0 + (dobin ? STR2NR_BIN : 0)
|
0 + (dobin ? STR2NR_BIN : 0)
|
||||||
+ (dooct ? STR2NR_OCT : 0)
|
+ (dooct ? STR2NR_OCT : 0)
|
||||||
+ (dohex ? STR2NR_HEX : 0),
|
+ (dohex ? STR2NR_HEX : 0),
|
||||||
NULL, &n, maxlen);
|
NULL, &n, maxlen, FALSE);
|
||||||
|
|
||||||
/* ignore leading '-' for hex and octal and bin numbers */
|
/* ignore leading '-' for hex and octal and bin numbers */
|
||||||
if (pre && negative)
|
if (pre && negative)
|
||||||
|
|||||||
@@ -4762,10 +4762,10 @@ do_set(
|
|||||||
/* Allow negative (for 'undolevels'), octal and
|
/* Allow negative (for 'undolevels'), octal and
|
||||||
* hex numbers. */
|
* hex numbers. */
|
||||||
vim_str2nr(arg, NULL, &i, STR2NR_ALL,
|
vim_str2nr(arg, NULL, &i, STR2NR_ALL,
|
||||||
&value, NULL, 0);
|
&value, NULL, 0, TRUE);
|
||||||
if (arg[i] != NUL && !VIM_ISWHITE(arg[i]))
|
if (i == 0 || (arg[i] != NUL && !VIM_ISWHITE(arg[i])))
|
||||||
{
|
{
|
||||||
errmsg = e_invarg;
|
errmsg = N_("E521: Number required after =");
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ char_u *skiptowhite(char_u *p);
|
|||||||
char_u *skiptowhite_esc(char_u *p);
|
char_u *skiptowhite_esc(char_u *p);
|
||||||
long getdigits(char_u **pp);
|
long getdigits(char_u **pp);
|
||||||
int vim_isblankline(char_u *lbuf);
|
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);
|
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 hex2nr(int c);
|
||||||
int hexhex2nr(char_u *p);
|
int hexhex2nr(char_u *p);
|
||||||
int rem_backslash(char_u *str);
|
int rem_backslash(char_u *str);
|
||||||
|
|||||||
@@ -512,3 +512,14 @@ func Test_empty_concatenate()
|
|||||||
call assert_equal('b', 'a'[4:0] . 'b')
|
call assert_equal('b', 'a'[4:0] . 'b')
|
||||||
call assert_equal('b', 'b' . 'a'[4:0])
|
call assert_equal('b', 'b' . 'a'[4:0])
|
||||||
endfunc
|
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
|
||||||
|
|||||||
@@ -176,6 +176,10 @@ func Test_json_decode()
|
|||||||
|
|
||||||
call assert_fails('call json_decode("{{}:42}")', "E474:")
|
call assert_fails('call json_decode("{{}:42}")', "E474:")
|
||||||
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
|
endfunc
|
||||||
|
|
||||||
let s:jsl5 = '[7,,,]'
|
let s:jsl5 = '[7,,,]'
|
||||||
|
|||||||
@@ -767,6 +767,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1355,
|
||||||
/**/
|
/**/
|
||||||
1354,
|
1354,
|
||||||
/**/
|
/**/
|
||||||
|
|||||||
Reference in New Issue
Block a user