diff src/userfunc.c @ 30166:d1c04b4dc60d v9.0.0419

patch 9.0.0419: the :defer command does not check the function arguments Commit: https://github.com/vim/vim/commit/169003289fb4b2ad18fd7f5807e0d05efff0be85 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Sep 8 19:51:45 2022 +0100 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.
author Bram Moolenaar <Bram@vim.org>
date Thu, 08 Sep 2022 21:00:04 +0200
parents 0fe61fa4e5d1
children d3cfd12839ef
line wrap: on
line diff
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -5608,6 +5608,7 @@ ex_call_inner(
 ex_defer_inner(
 	char_u	    *name,
 	char_u	    **arg,
+	type_T	    *type,
 	partial_T   *partial,
 	evalarg_T   *evalarg)
 {
@@ -5640,6 +5641,44 @@ ex_defer_inner(
     r = get_func_arguments(arg, evalarg, FALSE,
 					    argvars + partial_argc, &argcount);
     argcount += partial_argc;
+
+    if (r == OK)
+    {
+	if (type != NULL)
+	{
+	    // Check that the arguments are OK for the types of the funcref.
+	    r = check_argument_types(type, argvars, argcount, NULL, name);
+	}
+	else if (builtin_function(name, -1))
+	{
+	    int idx = find_internal_func(name);
+
+	    if (idx < 0)
+	    {
+		emsg_funcname(e_unknown_function_str, name);
+		r = FAIL;
+	    }
+	    else if (check_internal_func(idx, argcount) == -1)
+		r = FAIL;
+	}
+	else
+	{
+	    ufunc_T *ufunc = find_func(name, FALSE);
+
+	    // 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)
@@ -5839,7 +5878,7 @@ ex_call(exarg_T *eap)
     if (eap->cmdidx == CMD_defer)
     {
 	arg = startarg;
-	failed = ex_defer_inner(name, &arg, partial, &evalarg) == FAIL;
+	failed = ex_defer_inner(name, &arg, type, partial, &evalarg) == FAIL;
     }
     else
     {