Patch 8.2.1879
Problem:    Vim9: argument types of insert() not checked when compiling.
Solution:   Add argument type checks for insert().
Files:      src/evalfunc.c, src/proto/evalfunc.pro, src/vim9compile.c,
            src/testdir/test_vim9_builtin.vim


*** ../vim-8.2.1878/src/evalfunc.c      2020-10-21 14:49:05.033959899 +0200
--- src/evalfunc.c      2020-10-21 16:34:45.971094405 +0200
***************
*** 266,273 ****
  
  // Context passed to an arg_ function.
  typedef struct {
!     int               arg_count;  // actual argument count
!     int               arg_idx;    // current argument index (first arg is 
zero)
  } argcontext_T;
  
  // A function to check one argument type.  The first argument is the type to
--- 266,274 ----
  
  // Context passed to an arg_ function.
  typedef struct {
!     int               arg_count;      // actual argument count
!     type_T    **arg_types;    // list of argument types
!     int               arg_idx;        // current argument index (first arg is 
zero)
  } argcontext_T;
  
  // A function to check one argument type.  The first argument is the type to
***************
*** 278,293 ****
      static int
  arg_float_or_nr(type_T *type, argcontext_T *context)
  {
!     if (type->tt_type == VAR_FLOAT || type->tt_type == VAR_NUMBER)
        return OK;
      arg_type_mismatch(&t_number, type, context->arg_idx + 1);
      return FAIL;
  }
  
  /*
   * Lists of functions that check the argument types of a builtin function.
   */
  argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
  
  /*
   * Functions that return the return type of a builtin function.
--- 279,333 ----
      static int
  arg_float_or_nr(type_T *type, argcontext_T *context)
  {
!     if (type->tt_type == VAR_ANY
!                 || type->tt_type == VAR_FLOAT || type->tt_type == VAR_NUMBER)
        return OK;
      arg_type_mismatch(&t_number, type, context->arg_idx + 1);
      return FAIL;
  }
  
+     static int
+ arg_number(type_T *type, argcontext_T *context)
+ {
+     return check_type(&t_number, type, TRUE, context->arg_idx + 1);
+ }
+ 
+     static int
+ arg_list_or_blob(type_T *type, argcontext_T *context)
+ {
+     if (type->tt_type == VAR_ANY
+                    || type->tt_type == VAR_LIST || type->tt_type == VAR_BLOB)
+       return OK;
+     arg_type_mismatch(&t_list_any, type, context->arg_idx + 1);
+     return FAIL;
+ }
+ 
+ /*
+  * Check the type is an item of the list or blob of the previous arg.
+  * Must not be used for the first argcheck_T entry.
+  */
+     static int
+ arg_item_of_prev(type_T *type, argcontext_T *context)
+ {
+     type_T *prev_type = context->arg_types[context->arg_idx - 1];
+     type_T *expected;
+ 
+     if (prev_type->tt_type == VAR_LIST)
+       expected = prev_type->tt_member;
+     else if (prev_type->tt_type == VAR_BLOB)
+       expected = &t_number;
+     else
+       // probably VAR_ANY, can't check
+       return OK;
+ 
+     return check_type(expected, type, TRUE, context->arg_idx + 1);
+ }
+ 
  /*
   * Lists of functions that check the argument types of a builtin function.
   */
  argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
+ argcheck_T arg3_insert[] = {arg_list_or_blob, arg_item_of_prev, arg_number};
  
  /*
   * Functions that return the return type of a builtin function.
***************
*** 936,942 ****
                        ret_number,         f_inputsave},
      {"inputsecret",   1, 2, FEARG_1,      NULL,
                        ret_string,         f_inputsecret},
!     {"insert",                2, 3, FEARG_1,      NULL,
                        ret_first_arg,      f_insert},
      {"interrupt",     0, 0, 0,            NULL,
                        ret_void,           f_interrupt},
--- 976,982 ----
                        ret_number,         f_inputsave},
      {"inputsecret",   1, 2, FEARG_1,      NULL,
                        ret_string,         f_inputsecret},
!     {"insert",                2, 3, FEARG_1,      arg3_insert,
                        ret_first_arg,      f_insert},
      {"interrupt",     0, 0, 0,            NULL,
                        ret_void,           f_interrupt},
***************
*** 1763,1769 ****
   * Return FAIL and gives an error message when a type is wrong.
   */
      int
! internal_func_check_arg_types(type_T *types, int idx, int argcount)
  {
      argcheck_T        *argchecks = global_functions[idx].f_argcheck;
      int               i;
--- 1803,1809 ----
   * Return FAIL and gives an error message when a type is wrong.
   */
      int
! internal_func_check_arg_types(type_T **types, int idx, int argcount)
  {
      argcheck_T        *argchecks = global_functions[idx].f_argcheck;
      int               i;
***************
*** 1773,1783 ****
        argcontext_T context;
  
        context.arg_count = argcount;
        for (i = 0; i < argcount; ++i)
            if (argchecks[i] != NULL)
            {
                context.arg_idx = i;
!               if (argchecks[i](types + i, &context) == FAIL)
                    return FAIL;
            }
      }
--- 1813,1824 ----
        argcontext_T context;
  
        context.arg_count = argcount;
+       context.arg_types = types;
        for (i = 0; i < argcount; ++i)
            if (argchecks[i] != NULL)
            {
                context.arg_idx = i;
!               if (argchecks[i](types[i], &context) == FAIL)
                    return FAIL;
            }
      }
*** ../vim-8.2.1878/src/proto/evalfunc.pro      2020-10-21 14:24:51.178015688 
+0200
--- src/proto/evalfunc.pro      2020-10-21 16:35:42.202937833 +0200
***************
*** 4,10 ****
  int find_internal_func(char_u *name);
  int has_internal_func(char_u *name);
  char *internal_func_name(int idx);
! int internal_func_check_arg_types(type_T *types, int idx, int argcount);
  type_T *internal_func_ret_type(int idx, int argcount, type_T **argtypes);
  int check_internal_func(int idx, int argcount);
  int call_internal_func(char_u *name, int argcount, typval_T *argvars, 
typval_T *rettv);
--- 4,10 ----
  int find_internal_func(char_u *name);
  int has_internal_func(char_u *name);
  char *internal_func_name(int idx);
! int internal_func_check_arg_types(type_T **types, int idx, int argcount);
  type_T *internal_func_ret_type(int idx, int argcount, type_T **argtypes);
  int check_internal_func(int idx, int argcount);
  int call_internal_func(char_u *name, int argcount, typval_T *argvars, 
typval_T *rettv);
*** ../vim-8.2.1878/src/vim9compile.c   2020-10-21 14:24:51.178015688 +0200
--- src/vim9compile.c   2020-10-21 16:35:22.594992488 +0200
***************
*** 1478,1484 ****
      // Check the types of the arguments.
      argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount;
      if (argcount > 0 && internal_func_check_arg_types(
!                                       *argtypes, func_idx, argcount) == FAIL)
            return FAIL;
  
      if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
--- 1478,1484 ----
      // Check the types of the arguments.
      argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount;
      if (argcount > 0 && internal_func_check_arg_types(
!                                       argtypes, func_idx, argcount) == FAIL)
            return FAIL;
  
      if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
*** ../vim-8.2.1878/src/testdir/test_vim9_builtin.vim   2020-10-21 
14:24:51.178015688 +0200
--- src/testdir/test_vim9_builtin.vim   2020-10-21 16:39:40.290269550 +0200
***************
*** 318,330 ****
    index(['a', 'b', 'a', 'B'], 'b', 2, true)->assert_equal(3)
  enddef
  
! def Test_insert_return_type()
    var l = insert([2, 1], 3)
    var res = 0
    for n in l
      res += n
    endfor
    res->assert_equal(6)
  enddef
  
  def Test_keys_return_type()
--- 318,337 ----
    index(['a', 'b', 'a', 'B'], 'b', 2, true)->assert_equal(3)
  enddef
  
! def Test_insert()
    var l = insert([2, 1], 3)
    var res = 0
    for n in l
      res += n
    endfor
    res->assert_equal(6)
+ 
+   assert_equal([1, 2, 3], insert([2, 3], 1))
+   assert_equal([1, 2, 3], insert([1, 2], 3, 2))
+   assert_equal(['a', 'b', 'c'], insert(['b', 'c'], 'a'))
+   assert_equal(0z1234, insert(0z34, 0x12))
+   CheckDefFailure(['insert([2, 3], "a")'], 'E1013: Argument 2: type mismatch, 
expected number but got string', 1)
+   CheckDefFailure(['insert([2, 3], 1, "x")'], 'E1013: Argument 3: type 
mismatch, expected number but got string', 1)
  enddef
  
  def Test_keys_return_type()
*** ../vim-8.2.1878/src/version.c       2020-10-21 16:10:16.382485983 +0200
--- src/version.c       2020-10-21 16:25:06.216657068 +0200
***************
*** 752,753 ****
--- 752,755 ----
  {   /* Add new patch number below this line */
+ /**/
+     1879,
  /**/

-- 
hundred-and-one symptoms of being an internet addict:
95. Only communication in your household is through email.

 /// Bram Moolenaar -- b...@moolenaar.net -- 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 vim_dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/vim_dev/202010211445.09LEj8e4071260%40masaka.moolenaar.net.

Raspunde prin e-mail lui