]> granicus.if.org Git - vim/commitdiff
patch 8.2.4224: Vim9: no error when using a number for map() second argument v8.2.4224
authorBram Moolenaar <Bram@vim.org>
Wed, 26 Jan 2022 18:26:21 +0000 (18:26 +0000)
committerBram Moolenaar <Bram@vim.org>
Wed, 26 Jan 2022 18:26:21 +0000 (18:26 +0000)
Problem:    Vim9: no error when using a number for map() second argument
Solution:   Disallow number to string conversion. (closes #9630)

src/eval.c
src/evalfunc.c
src/testdir/test_vim9_builtin.vim
src/version.c

index 72b1d6c97463a8801900f7b6a4aa35a0a9c60d16..7bc37f23766d8a5466621fa197f2897d81be2d20 100644 (file)
@@ -291,7 +291,7 @@ eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
     }
     else
     {
-       s = tv_get_string_buf_chk(expr, buf);
+       s = tv_get_string_buf_chk_strict(expr, buf, TRUE);
        if (s == NULL)
            return FAIL;
        s = skipwhite(s);
index b838c395d66a4723be21c0968c083224004aca82..4376318d0d31d63d457ddc2c0bc652ebce4acfb1 100644 (file)
@@ -491,13 +491,26 @@ arg_list_or_dict_or_blob_or_string(type_T *type, type_T *decl_type UNUSED, argco
     static int
 arg_filter_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
 {
-    if (type->tt_type == VAR_FUNC
-           && !(type->tt_member->tt_type == VAR_BOOL
+    if (type->tt_type == VAR_STRING
+           || type->tt_type == VAR_PARTIAL
+           || type == &t_unknown
+           || type == &t_any)
+       return OK;
+
+    if (type->tt_type == VAR_FUNC)
+    {
+       if (!(type->tt_member->tt_type == VAR_BOOL
                || type->tt_member->tt_type == VAR_NUMBER
                || type->tt_member->tt_type == VAR_UNKNOWN
                || type->tt_member->tt_type == VAR_ANY))
+       {
+           arg_type_mismatch(&t_func_bool, type, context->arg_idx + 1);
+           return FAIL;
+       }
+    }
+    else
     {
-       arg_type_mismatch(&t_func_bool, type, context->arg_idx + 1);
+       semsg(_(e_string_or_function_required_for_argument_nr), 2);
        return FAIL;
     }
     return OK;
@@ -509,27 +522,40 @@ arg_filter_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
     static int
 arg_map_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context)
 {
-    if (type->tt_type == VAR_FUNC
-           && type->tt_member != &t_any
-           && type->tt_member != &t_unknown)
-    {
-       type_T *expected = NULL;
+    if (type->tt_type == VAR_STRING
+           || type->tt_type == VAR_PARTIAL
+           || type == &t_unknown
+           || type == &t_any)
+       return OK;
 
-       if (context->arg_types[0].type_curr->tt_type == VAR_LIST
-               || context->arg_types[0].type_curr->tt_type == VAR_DICT)
-           expected = context->arg_types[0].type_curr->tt_member;
-       else if (context->arg_types[0].type_curr->tt_type == VAR_STRING)
-           expected = &t_string;
-       else if (context->arg_types[0].type_curr->tt_type == VAR_BLOB)
-           expected = &t_number;
-       if (expected != NULL)
+    if (type->tt_type == VAR_FUNC)
+    {
+       if (type->tt_member != &t_any
+           && type->tt_member != &t_unknown)
        {
-           type_T t_func_exp = {VAR_FUNC, -1, 0, TTFLAG_STATIC, NULL, NULL};
+           type_T *expected = NULL;
+
+           if (context->arg_types[0].type_curr->tt_type == VAR_LIST
+                   || context->arg_types[0].type_curr->tt_type == VAR_DICT)
+               expected = context->arg_types[0].type_curr->tt_member;
+           else if (context->arg_types[0].type_curr->tt_type == VAR_STRING)
+               expected = &t_string;
+           else if (context->arg_types[0].type_curr->tt_type == VAR_BLOB)
+               expected = &t_number;
+           if (expected != NULL)
+           {
+               type_T t_func_exp = {VAR_FUNC, -1, 0, TTFLAG_STATIC, NULL, NULL};
 
-           t_func_exp.tt_member = expected;
-           return check_arg_type(&t_func_exp, type, context);
+               t_func_exp.tt_member = expected;
+               return check_arg_type(&t_func_exp, type, context);
+           }
        }
     }
+    else
+    {
+       semsg(_(e_string_or_function_required_for_argument_nr), 2);
+       return FAIL;
+    }
     return OK;
 }
 
index 3747a4e19f8fe0336d2442ff1e1fa9b8b34c640a..a00133f14c21825ac4ad29c57c21e1cacf5466f5 100644 (file)
@@ -1275,6 +1275,7 @@ enddef
 
 def Test_filter()
   CheckDefAndScriptFailure(['filter(1.1, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got float', 'E1251: List, Dictionary, Blob or String required for argument 1'])
+  CheckDefAndScriptFailure(['filter([1, 2], 4)'], ['E1256: String or function required for argument 2', 'E1024: Using a Number as a String'])
 
   var lines =<< trim END
     def F(i: number, v: any): string
@@ -2153,6 +2154,7 @@ def Test_map()
     CheckDefAndScriptFailure(['map(test_null_channel(), "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got channel', 'E1251: List, Dictionary, Blob or String required for argument 1'])
   endif
   CheckDefAndScriptFailure(['map(1, "1")'], ['E1013: Argument 1: type mismatch, expected list<any> but got number', 'E1251: List, Dictionary, Blob or String required for argument 1'])
+  CheckDefAndScriptFailure(['map([1, 2], 4)'], ['E1256: String or function required for argument 2', 'E1024: Using a Number as a String'])
 
   # type of dict remains dict<any> even when type of values changes
   # same for list
index e6f8b3a09b8058c8a0453d004e49254d04b54b68..9869aa0d810d6d274ea3755d569ecadebd44f959 100644 (file)
@@ -750,6 +750,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    4224,
 /**/
     4223,
 /**/