]> granicus.if.org Git - vim/commitdiff
patch 8.2.1879: Vim9: argument types of insert() not checked when compiling v8.2.1879
authorBram Moolenaar <Bram@vim.org>
Wed, 21 Oct 2020 14:42:22 +0000 (16:42 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 21 Oct 2020 14:42:22 +0000 (16:42 +0200)
Problem:    Vim9: argument types of insert() not checked when compiling.
Solution:   Add argument type checks for insert().

src/evalfunc.c
src/proto/evalfunc.pro
src/testdir/test_vim9_builtin.vim
src/version.c
src/vim9compile.c

index d782d8494dd8e7db3cb99c041eb1916da6bb63c5..41133091d5d3b6993c3a7362d06a154842ee964f 100644 (file)
@@ -266,8 +266,9 @@ static void f_xor(typval_T *argvars, typval_T *rettv);
 
 // Context passed to an arg_ function.
 typedef struct {
-    int                arg_count;  // actual argument count
-    int                arg_idx;    // current argument index (first arg is zero)
+    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,16 +279,55 @@ typedef int (*argcheck_T)(type_T *, argcontext_T *);
     static int
 arg_float_or_nr(type_T *type, argcontext_T *context)
 {
-    if (type->tt_type == VAR_FLOAT || type->tt_type == VAR_NUMBER)
+    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,7 +976,7 @@ static funcentry_T global_functions[] =
                        ret_number,         f_inputsave},
     {"inputsecret",    1, 2, FEARG_1,      NULL,
                        ret_string,         f_inputsecret},
-    {"insert",         2, 3, FEARG_1,      NULL,
+    {"insert",         2, 3, FEARG_1,      arg3_insert,
                        ret_first_arg,      f_insert},
     {"interrupt",      0, 0, 0,            NULL,
                        ret_void,           f_interrupt},
@@ -1763,7 +1803,7 @@ internal_func_name(int idx)
  * 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)
+internal_func_check_arg_types(type_T **types, int idx, int argcount)
 {
     argcheck_T *argchecks = global_functions[idx].f_argcheck;
     int                i;
@@ -1773,11 +1813,12 @@ internal_func_check_arg_types(type_T *types, int idx, int argcount)
        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)
+               if (argchecks[i](types[i], &context) == FAIL)
                    return FAIL;
            }
     }
index 6cc81db0c3bcadc5f29b36f4bcf029bf5f9a185b..c649b861b16c5e401754396a080d4c7810663d1b 100644 (file)
@@ -4,7 +4,7 @@ char_u *get_expr_name(expand_T *xp, int idx);
 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);
+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);
index fb94746c7e36228f15cbee7ecbcfd574b1626f76..e3d7bb628d957b16e95e5ea7e186f51ddff5f4c8 100644 (file)
@@ -318,13 +318,20 @@ def Test_index()
   index(['a', 'b', 'a', 'B'], 'b', 2, true)->assert_equal(3)
 enddef
 
-def Test_insert_return_type()
+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()
index 78e47525a09212742a507afa08f3dcf6a05bebff..a49bdd386885dce7c3d9adce702793d83cfe204c 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1879,
 /**/
     1878,
 /**/
index 289b941bf4aa8d0dea15b5f3ec0fd59723e8eb6c..8ef1f087341af08381b4076d052939f825dd1a22 100644 (file)
@@ -1478,7 +1478,7 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
     // 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)
+                                       argtypes, func_idx, argcount) == FAIL)
            return FAIL;
 
     if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)