Mercurial > vim
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