diff options
author | zeertzjq <zeertzjq@outlook.com> | 2023-04-17 09:08:25 +0800 |
---|---|---|
committer | zeertzjq <zeertzjq@outlook.com> | 2023-04-17 09:38:09 +0800 |
commit | 7a3f86481e96e5c30db5af74760e475bac8cc403 (patch) | |
tree | 32a6104e5d40df885d884bd72d20a0c9a54e1390 /src/nvim/eval/userfunc.c | |
parent | 6bfba3660c5fbb22104cd87bd66a1381007fca22 (diff) | |
download | rneovim-7a3f86481e96e5c30db5af74760e475bac8cc403.tar.gz rneovim-7a3f86481e96e5c30db5af74760e475bac8cc403.tar.bz2 rneovim-7a3f86481e96e5c30db5af74760e475bac8cc403.zip |
vim-patch:9.0.0419: the :defer command does not check the function arguments
Problem: The :defer command does not check the function argument count and
types.
Solution: Check the function arguments when adding a deferred function.
https://github.com/vim/vim/commit/169003289fb4b2ad18fd7f5807e0d05efff0be85
Cherry-pick check_internal_func() from Vim, but use EvalFuncDef pointer
as first argument.
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Diffstat (limited to 'src/nvim/eval/userfunc.c')
-rw-r--r-- | src/nvim/eval/userfunc.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 32f9f9182c..65918ba2bf 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -72,7 +72,7 @@ static funccall_T *current_funccal = NULL; // item in it is still being used. static funccall_T *previous_funccal = NULL; -static const char *e_unknownfunc = N_("E117: Unknown function: %s"); +static const char *e_unknown_function_str = N_("E117: Unknown function: %s"); static const char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it"); static const char *e_funcdict = N_("E717: Dictionary entry already exists"); static const char *e_funcref = N_("E718: Funcref required"); @@ -1523,14 +1523,14 @@ varnumber_T callback_call_retnr(Callback *callback, int argcount, typval_T *argv /// Give an error message for the result of a function. /// Nothing if "error" is FCERR_NONE. static void user_func_error(int error, const char *name, funcexe_T *funcexe) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ARG(2) { switch (error) { case FCERR_UNKNOWN: if (funcexe->fe_found_var) { semsg(_(e_not_callable_type_str), name); } else { - emsg_funcname(e_unknownfunc, name); + emsg_funcname(e_unknown_function_str, name); } break; case FCERR_NOTMETHOD: @@ -1543,7 +1543,7 @@ static void user_func_error(int error, const char *name, funcexe_T *funcexe) emsg_funcname(_(e_toomanyarg), name); break; case FCERR_TOOFEW: - emsg_funcname(N_("E119: Not enough arguments for function: %s"), name); + emsg_funcname(_(e_toofewarg), name); break; case FCERR_SCRIPT: emsg_funcname(N_("E120: Using <SID> not in a script context: %s"), name); @@ -3172,6 +3172,29 @@ static int ex_defer_inner(char *name, char **arg, const partial_T *const partial } int r = get_func_arguments(arg, evalarg, false, argvars + partial_argc, &argcount); argcount += partial_argc; + + if (r == OK) { + if (builtin_function(name, -1)) { + const EvalFuncDef *const fdef = find_internal_func(name); + if (fdef == NULL) { + emsg_funcname(e_unknown_function_str, name); + r = FAIL; + } else if (check_internal_func(fdef, argcount) == -1) { + r = FAIL; + } + } else { + ufunc_T *ufunc = find_func(name); + // we tolerate an unknown function here, it might be defined later + if (ufunc != NULL) { + int error = check_user_func_argcount(ufunc, argcount); + if (error != FCERR_UNKNOWN) { + user_func_error(error, name, NULL); + r = FAIL; + } + } + } + } + if (r == FAIL) { while (--argcount >= 0) { tv_clear(&argvars[argcount]); |