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.

Raspunde prin e-mail lui