mirror of
https://github.com/vim/vim.git
synced 2025-09-26 04:04:07 -04:00
patch 8.2.1879: Vim9: argument types of insert() not checked when compiling
Problem: Vim9: argument types of insert() not checked when compiling. Solution: Add argument type checks for insert().
This commit is contained in:
@@ -266,8 +266,9 @@ static void f_xor(typval_T *argvars, typval_T *rettv);
|
|||||||
|
|
||||||
// Context passed to an arg_ function.
|
// Context passed to an arg_ function.
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int arg_count; // actual argument count
|
int arg_count; // actual argument count
|
||||||
int arg_idx; // current argument index (first arg is zero)
|
type_T **arg_types; // list of argument types
|
||||||
|
int arg_idx; // current argument index (first arg is zero)
|
||||||
} argcontext_T;
|
} argcontext_T;
|
||||||
|
|
||||||
// A function to check one argument type. The first argument is the type to
|
// 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
|
static int
|
||||||
arg_float_or_nr(type_T *type, argcontext_T *context)
|
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;
|
return OK;
|
||||||
arg_type_mismatch(&t_number, type, context->arg_idx + 1);
|
arg_type_mismatch(&t_number, type, context->arg_idx + 1);
|
||||||
return FAIL;
|
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.
|
* Lists of functions that check the argument types of a builtin function.
|
||||||
*/
|
*/
|
||||||
argcheck_T arg1_float_or_nr[] = {arg_float_or_nr};
|
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.
|
* Functions that return the return type of a builtin function.
|
||||||
@@ -936,7 +976,7 @@ static funcentry_T global_functions[] =
|
|||||||
ret_number, f_inputsave},
|
ret_number, f_inputsave},
|
||||||
{"inputsecret", 1, 2, FEARG_1, NULL,
|
{"inputsecret", 1, 2, FEARG_1, NULL,
|
||||||
ret_string, f_inputsecret},
|
ret_string, f_inputsecret},
|
||||||
{"insert", 2, 3, FEARG_1, NULL,
|
{"insert", 2, 3, FEARG_1, arg3_insert,
|
||||||
ret_first_arg, f_insert},
|
ret_first_arg, f_insert},
|
||||||
{"interrupt", 0, 0, 0, NULL,
|
{"interrupt", 0, 0, 0, NULL,
|
||||||
ret_void, f_interrupt},
|
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.
|
* Return FAIL and gives an error message when a type is wrong.
|
||||||
*/
|
*/
|
||||||
int
|
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;
|
argcheck_T *argchecks = global_functions[idx].f_argcheck;
|
||||||
int i;
|
int i;
|
||||||
@@ -1773,11 +1813,12 @@ internal_func_check_arg_types(type_T *types, int idx, int argcount)
|
|||||||
argcontext_T context;
|
argcontext_T context;
|
||||||
|
|
||||||
context.arg_count = argcount;
|
context.arg_count = argcount;
|
||||||
|
context.arg_types = types;
|
||||||
for (i = 0; i < argcount; ++i)
|
for (i = 0; i < argcount; ++i)
|
||||||
if (argchecks[i] != NULL)
|
if (argchecks[i] != NULL)
|
||||||
{
|
{
|
||||||
context.arg_idx = i;
|
context.arg_idx = i;
|
||||||
if (argchecks[i](types + i, &context) == FAIL)
|
if (argchecks[i](types[i], &context) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,7 +4,7 @@ char_u *get_expr_name(expand_T *xp, int idx);
|
|||||||
int find_internal_func(char_u *name);
|
int find_internal_func(char_u *name);
|
||||||
int has_internal_func(char_u *name);
|
int has_internal_func(char_u *name);
|
||||||
char *internal_func_name(int idx);
|
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);
|
type_T *internal_func_ret_type(int idx, int argcount, type_T **argtypes);
|
||||||
int check_internal_func(int idx, int argcount);
|
int check_internal_func(int idx, int argcount);
|
||||||
int call_internal_func(char_u *name, int argcount, typval_T *argvars, typval_T *rettv);
|
int call_internal_func(char_u *name, int argcount, typval_T *argvars, typval_T *rettv);
|
||||||
|
@@ -318,13 +318,20 @@ def Test_index()
|
|||||||
index(['a', 'b', 'a', 'B'], 'b', 2, true)->assert_equal(3)
|
index(['a', 'b', 'a', 'B'], 'b', 2, true)->assert_equal(3)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_insert_return_type()
|
def Test_insert()
|
||||||
var l = insert([2, 1], 3)
|
var l = insert([2, 1], 3)
|
||||||
var res = 0
|
var res = 0
|
||||||
for n in l
|
for n in l
|
||||||
res += n
|
res += n
|
||||||
endfor
|
endfor
|
||||||
res->assert_equal(6)
|
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
|
enddef
|
||||||
|
|
||||||
def Test_keys_return_type()
|
def Test_keys_return_type()
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1879,
|
||||||
/**/
|
/**/
|
||||||
1878,
|
1878,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -1478,7 +1478,7 @@ generate_BCALL(cctx_T *cctx, int func_idx, int argcount, int method_call)
|
|||||||
// Check the types of the arguments.
|
// Check the types of the arguments.
|
||||||
argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount;
|
argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount;
|
||||||
if (argcount > 0 && internal_func_check_arg_types(
|
if (argcount > 0 && internal_func_check_arg_types(
|
||||||
*argtypes, func_idx, argcount) == FAIL)
|
argtypes, func_idx, argcount) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
|
if ((isn = generate_instr(cctx, ISN_BCALL)) == NULL)
|
||||||
|
Reference in New Issue
Block a user