]> granicus.if.org Git - vim/commitdiff
patch 8.1.1355: obvious mistakes are accepted as valid expressions v8.1.1355
authorBram Moolenaar <Bram@vim.org>
Sun, 19 May 2019 17:59:35 +0000 (19:59 +0200)
committerBram Moolenaar <Bram@vim.org>
Sun, 19 May 2019 17:59:35 +0000 (19:59 +0200)
Problem:    Obvious mistakes are accepted as valid expressions.
Solution:   Be more strict about parsing numbers. (Yasuhiro Matsumoto,
            closes #3981)

13 files changed:
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
src/version.c

index 3eb5b5805556632331f5de7bbbe7739666a91e81..cff62e18572b2c9c30fef11200046bbc404eda99 100644 (file)
@@ -1776,25 +1776,30 @@ vim_isblankline(char_u *lbuf)
  * 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                        *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                    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,9 +1841,7 @@ vim_str2nr(
        }
     }
 
-    /*
-    * Do the string-to-numeric conversion "manually" to avoid sscanf quirks.
-    */
+    // Do the conversion manually to avoid sscanf() quirks.
     n = 1;
     if (pre == 'B' || pre == 'b' || what == STR2NR_BIN + STR2NR_FORCE)
     {
@@ -1907,6 +1910,10 @@ vim_str2nr(
                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;
index c0c6aa7ad50ae52537dc0364234a39d4b3bd5f67..69503489999234fb585585cc7db1394d9b5031b7 100644 (file)
@@ -4453,7 +4453,13 @@ eval7(
                else
                {
                    // 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;
                    if (evaluate)
                    {
@@ -7460,7 +7466,7 @@ tv_get_number_chk(typval_T *varp, int *denote)
        case VAR_STRING:
            if (varp->vval.v_string != NULL)
                vim_str2nr(varp->vval.v_string, NULL, NULL,
-                                                   STR2NR_ALL, &n, NULL, 0);
+                                           STR2NR_ALL, &n, NULL, 0, FALSE);
            return n;
        case VAR_LIST:
            emsg(_("E745: Using a List as a Number"));
index 4c02e159b969166f1a2ad05b9b2c9e5a9b469f3a..5631795e35c91c27f3b5f71f2dcb9ffc72cd0c33 100644 (file)
@@ -13199,7 +13199,8 @@ f_str2nr(typval_T *argvars, typval_T *rettv)
        case 16: what = STR2NR_HEX + STR2NR_FORCE; break;
        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)
        rettv->vval.v_number = -n;
     else
index 964c4556c95798cfc71262e73c68e443faeec777..ff86d1cd47293d981ceab93b05744cd2342f30f3 100644 (file)
@@ -558,7 +558,8 @@ ex_sort(exarg_T *eap)
                {
                    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);
+                       &nrs[lnum - eap->line1].st_u.num.value,
+                       NULL, 0, FALSE);
                }
            }
 #ifdef FEAT_FLOAT
index f1c30a2d9d32489803bea03f24bacb78e6502b23..ba3dc7358a9bee5eda7d8a3766de05f3c52ed8dc 100644 (file)
@@ -6470,7 +6470,7 @@ get_list_range(char_u **str, int *num1, int *num2)
     *str = skipwhite(*str);
     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;
        *num1 = (int)num;
        first = TRUE;
@@ -6479,7 +6479,7 @@ get_list_range(char_u **str, int *num1, int *num2)
     if (**str == ',')                  /* parse "to" part of range */
     {
        *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)
        {
            *num2 = (int)num;
index 9fb6af0defd1ea4e8706115868a1107913526f92..8674bf26595bc18beb03b7105994d124574fcd98 100644 (file)
@@ -452,7 +452,12 @@ json_decode_string(js_read_T *reader, typval_T *res, int quote)
                    nr = 0;
                    len = 0;
                    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;
                    if (0xd800 <= nr && nr <= 0xdfff
                            && (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 */
                        len = 0;
                        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)
                        {
                            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,
                                    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)
                            {
                                cur_item->v_type = VAR_NUMBER;
index f9f6bf58e8c1be9452ad7eb775223de69be5df48..dac66ffb287a8220fe8f3d5cefdcb7fe84416a2c 100644 (file)
@@ -2832,7 +2832,12 @@ find_special_key(
            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);
+           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,7 +2869,12 @@ find_special_key(
                                                 && 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);
+               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
index 975a56f372ba7c1b96ccb680317172a843677a22..a989ce21155f90ade55a78bc12152ae788dedabb 100644 (file)
--- a/src/ops.c
+++ b/src/ops.c
@@ -5794,7 +5794,7 @@ do_addsub(
                0 + (dobin ? STR2NR_BIN : 0)
                    + (dooct ? STR2NR_OCT : 0)
                    + (dohex ? STR2NR_HEX : 0),
-               NULL, &n, maxlen);
+               NULL, &n, maxlen, FALSE);
 
        /* ignore leading '-' for hex and octal and bin numbers */
        if (pre && negative)
index a9b9780792e3dba03050f8034b72a305ac9e7f25..bfdf71799df6d5b1f968e82d0d6520579645b817 100644 (file)
@@ -4762,10 +4762,10 @@ do_set(
                            /* 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]))
+                                                    &value, NULL, 0, TRUE);
+                           if (i == 0 || (arg[i] != NUL && !VIM_ISWHITE(arg[i])))
                            {
-                               errmsg = e_invarg;
+                               errmsg = N_("E521: Number required after =");
                                goto skip;
                            }
                        }
index bb4132fe79a4327ac57d3c985ef1cb0255f2a48d..f60822ef006d6f5d5b71f3dece7cebf1dafc38e1 100644 (file)
@@ -54,7 +54,7 @@ char_u *skiptowhite(char_u *p);
 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);
+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);
index 216a00f7dbdf42fd66e781296b22a210de919f79..ccca79270c4e9752c88839dce31902b29ac253e0 100644 (file)
@@ -512,3 +512,14 @@ func Test_empty_concatenate()
   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
index e16a7f03076cd6adaecfd2877d9ed354324952ed..8f85a58cf06ab1a39b7a5000f6fe569026d054f9 100644 (file)
@@ -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("\"\\u111Z\"")', 'E474:')
+  call assert_equal('[😂]', json_decode('"[\uD83D\uDE02]"'))
+  call assert_equal('a😂b', json_decode('"a\uD83D\uDE02b"'))
 endfunc
 
 let s:jsl5 = '[7,,,]'
index 6d2416d1353fc541362de71d65e3301efc1d3f07..042a8bcd997a571b3a61bf29f2069a7faf242672 100644 (file)
@@ -767,6 +767,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1355,
 /**/
     1354,
 /**/