mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 9.0.1559: function argument types not always checked
Problem: Function argument types not always checked and using v:none may cause an error. Solution: Check argument types once the function type is known. Do not give an error for using v:none as an argument. (closes #12200)
This commit is contained in:
parent
a2c0028fdf
commit
2ba51236fb
@ -778,6 +778,38 @@ def Test_using_vnone_default()
|
|||||||
END
|
END
|
||||||
v9.CheckScriptSuccess(lines)
|
v9.CheckScriptSuccess(lines)
|
||||||
|
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
export def Floats(x: float, y = 2.0, z = 5.0)
|
||||||
|
g:result = printf("%.2f %.2f %.2f", x, y, z)
|
||||||
|
enddef
|
||||||
|
END
|
||||||
|
writefile(lines, 'Xlib.vim', 'D')
|
||||||
|
|
||||||
|
# test using a function reference in script-local variable
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
import './Xlib.vim'
|
||||||
|
const Floatfunc = Xlib.Floats
|
||||||
|
Floatfunc(1.0, v:none, 3.0)
|
||||||
|
END
|
||||||
|
v9.CheckScriptSuccess(lines)
|
||||||
|
assert_equal('1.00 2.00 3.00', g:result)
|
||||||
|
unlet g:result
|
||||||
|
|
||||||
|
# test calling the imported function
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
|
||||||
|
import './Xlib.vim'
|
||||||
|
Xlib.Floats(1.0, v:none, 3.0)
|
||||||
|
END
|
||||||
|
v9.CheckScriptSuccess(lines)
|
||||||
|
assert_equal('1.00 2.00 3.00', g:result)
|
||||||
|
unlet g:result
|
||||||
|
|
||||||
# TODO: this should give an error for using a missing argument
|
# TODO: this should give an error for using a missing argument
|
||||||
# lines =<< trim END
|
# lines =<< trim END
|
||||||
# vim9script
|
# vim9script
|
||||||
|
@ -3595,6 +3595,34 @@ user_func_error(funcerror_T error, char_u *name, int found_var)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check the argument types "argvars[argcount]" for "name" using the
|
||||||
|
* information in "funcexe". When "base_included" then "funcexe->fe_basetv"
|
||||||
|
* is already included in "argvars[]".
|
||||||
|
* Will do nothing if "funcexe->fe_check_type" is NULL or
|
||||||
|
* "funcexe->fe_evaluate" is FALSE;
|
||||||
|
* Returns an FCERR_ value.
|
||||||
|
*/
|
||||||
|
static funcerror_T
|
||||||
|
may_check_argument_types(
|
||||||
|
funcexe_T *funcexe,
|
||||||
|
typval_T *argvars,
|
||||||
|
int argcount,
|
||||||
|
int base_included,
|
||||||
|
char_u *name)
|
||||||
|
{
|
||||||
|
if (funcexe->fe_check_type != NULL && funcexe->fe_evaluate)
|
||||||
|
{
|
||||||
|
// Check that the argument types are OK for the types of the funcref.
|
||||||
|
if (check_argument_types(funcexe->fe_check_type,
|
||||||
|
argvars, argcount,
|
||||||
|
base_included ? NULL : funcexe->fe_basetv,
|
||||||
|
name) == FAIL)
|
||||||
|
return FCERR_OTHER;
|
||||||
|
}
|
||||||
|
return FCERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call a function with its resolved parameters
|
* Call a function with its resolved parameters
|
||||||
*
|
*
|
||||||
@ -3691,15 +3719,10 @@ call_func(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error == FCERR_NONE && funcexe->fe_check_type != NULL
|
if (error == FCERR_NONE)
|
||||||
&& funcexe->fe_evaluate)
|
// check the argument types if possible
|
||||||
{
|
error = may_check_argument_types(funcexe, argvars, argcount, FALSE,
|
||||||
// Check that the argument types are OK for the types of the funcref.
|
(name != NULL) ? name : funcname);
|
||||||
if (check_argument_types(funcexe->fe_check_type,
|
|
||||||
argvars, argcount, funcexe->fe_basetv,
|
|
||||||
(name != NULL) ? name : funcname) == FAIL)
|
|
||||||
error = FCERR_OTHER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error == FCERR_NONE && funcexe->fe_evaluate)
|
if (error == FCERR_NONE && funcexe->fe_evaluate)
|
||||||
{
|
{
|
||||||
@ -3761,10 +3784,20 @@ call_func(
|
|||||||
error = FCERR_DELETED;
|
error = FCERR_DELETED;
|
||||||
else if (fp != NULL)
|
else if (fp != NULL)
|
||||||
{
|
{
|
||||||
|
int need_arg_check = FALSE;
|
||||||
|
if (funcexe->fe_check_type == NULL)
|
||||||
|
{
|
||||||
|
funcexe->fe_check_type = fp->uf_func_type;
|
||||||
|
need_arg_check = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (funcexe->fe_argv_func != NULL)
|
if (funcexe->fe_argv_func != NULL)
|
||||||
|
{
|
||||||
// postponed filling in the arguments, do it now
|
// postponed filling in the arguments, do it now
|
||||||
argcount = funcexe->fe_argv_func(argcount, argvars,
|
argcount = funcexe->fe_argv_func(argcount, argvars,
|
||||||
argv_clear, fp);
|
argv_clear, fp);
|
||||||
|
need_arg_check = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (funcexe->fe_basetv != NULL)
|
if (funcexe->fe_basetv != NULL)
|
||||||
{
|
{
|
||||||
@ -3774,9 +3807,16 @@ call_func(
|
|||||||
argcount++;
|
argcount++;
|
||||||
argvars = argv;
|
argvars = argv;
|
||||||
argv_base = 1;
|
argv_base = 1;
|
||||||
|
need_arg_check = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = call_user_func_check(fp, argcount, argvars, rettv,
|
// Check the argument types now that the function type and all
|
||||||
|
// argument values are known, if not done above.
|
||||||
|
if (need_arg_check)
|
||||||
|
error = may_check_argument_types(funcexe, argvars, argcount,
|
||||||
|
TRUE, (name != NULL) ? name : funcname);
|
||||||
|
if (error == FCERR_NONE || error == FCERR_UNKNOWN)
|
||||||
|
error = call_user_func_check(fp, argcount, argvars, rettv,
|
||||||
funcexe, selfdict);
|
funcexe, selfdict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -695,6 +695,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 */
|
||||||
|
/**/
|
||||||
|
1559,
|
||||||
/**/
|
/**/
|
||||||
1558,
|
1558,
|
||||||
/**/
|
/**/
|
||||||
|
@ -970,7 +970,10 @@ check_argument_types(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
expected = type->tt_args[i];
|
expected = type->tt_args[i];
|
||||||
if (check_typval_arg_type(expected, tv, NULL, i + 1) == FAIL)
|
|
||||||
|
// check the type, unless the value is v:none
|
||||||
|
if ((tv->v_type != VAR_SPECIAL || tv->vval.v_number != VVAL_NONE)
|
||||||
|
&& check_typval_arg_type(expected, tv, NULL, i + 1) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user