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 -- Br...@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 ///