changeset 27392:ec2ba9acec1b v8.2.4224

patch 8.2.4224: Vim9: no error when using a number for map() second argument Commit: https://github.com/vim/vim/commit/1080c48ec8d672d7e9fbefb5a1255c9df09a2884 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Jan 26 18:26:21 2022 +0000 patch 8.2.4224: Vim9: no error when using a number for map() second argument Problem: Vim9: no error when using a number for map() second argument Solution: Disallow number to string conversion. (closes https://github.com/vim/vim/issues/9630)
author Bram Moolenaar <Bram@vim.org>
date Wed, 26 Jan 2022 19:30:03 +0100
parents 5854ea4dc132
children db7fa549029b
files src/eval.c src/evalfunc.c src/testdir/test_vim9_builtin.vim src/version.c
diffstat 4 files changed, 54 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -291,7 +291,7 @@ eval_expr_typval(typval_T *expr, typval_
     }
     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);
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -491,13 +491,26 @@ arg_list_or_dict_or_blob_or_string(type_
     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);
+	{
+	    arg_type_mismatch(&t_func_bool, type, context->arg_idx + 1);
+	    return FAIL;
+	}
+    }
+    else
+    {
+	semsg(_(e_string_or_function_required_for_argument_nr), 2);
 	return FAIL;
     }
     return OK;
@@ -509,26 +522,39 @@ arg_filter_func(type_T *type, type_T *de
     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
+    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 != &t_any
 	    && type->tt_member != &t_unknown)
-    {
-	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);
-	}
+	{
+	    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);
+	    }
+	}
+    }
+    else
+    {
+	semsg(_(e_string_or_function_required_for_argument_nr), 2);
+	return FAIL;
     }
     return OK;
 }
--- a/src/testdir/test_vim9_builtin.vim
+++ b/src/testdir/test_vim9_builtin.vim
@@ -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
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4224,
+/**/
     4223,
 /**/
     4222,