changeset 24065:a6aec9a89184 v8.2.2574

patch 8.2.2574: Vim9: crash when calling partial with wrong function Commit: https://github.com/vim/vim/commit/04947cc6ed313b6b99889c27d008c68a373df634 Author: Bram Moolenaar <Bram@vim.org> Date: Sat Mar 6 19:26:46 2021 +0100 patch 8.2.2574: Vim9: crash when calling partial with wrong function Problem: Vim9: crash when calling partial with wrong function. Solution: Check argument types of called function. (closes https://github.com/vim/vim/issues/7912)
author Bram Moolenaar <Bram@vim.org>
date Sat, 06 Mar 2021 19:30:02 +0100
parents 85e18722945c
children 425c76b8e17f
files src/testdir/test_vim9_func.vim src/version.c src/vim9execute.c
diffstat 3 files changed, 46 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -2367,6 +2367,30 @@ def Test_nested_lambda_in_closure()
   delete('XnestedDone')
 enddef
 
+def Test_check_func_arg_types()
+  var lines =<< trim END
+      vim9script
+      def F1(x: string): string
+        return x
+      enddef
+
+      def F2(x: number): number
+        return x + 1
+      enddef
+
+      def G(g: func): dict<func>
+        return {f: g}
+      enddef
+
+      def H(d: dict<func>): string
+        return d.f('a')
+      enddef
+  END
+
+  CheckScriptSuccess(lines + ['echo H(G(F1))'])
+  CheckScriptFailure(lines + ['echo H(G(F2))'], 'E1013:')
+enddef
+
 
 
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2574,
+/**/
     2573,
 /**/
     2572,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -797,7 +797,27 @@ call_by_name(char_u *name, int argcount,
     }
 
     if (ufunc != NULL)
+    {
+	if (ufunc->uf_arg_types != NULL)
+	{
+	    int i;
+	    typval_T	*argv = STACK_TV_BOT(0) - argcount;
+
+	    // The function can change at runtime, check that the argument
+	    // types are correct.
+	    for (i = 0; i < argcount; ++i)
+	    {
+		type_T *type = i < ufunc->uf_args.ga_len
+				  ? ufunc->uf_arg_types[i] : ufunc->uf_va_type;
+
+		if (type != NULL && check_typval_arg_type(type,
+						      &argv[i], i + 1) == FAIL)
+		    return FAIL;
+	    }
+	}
+
 	return call_ufunc(ufunc, NULL, argcount, ectx, iptr);
+    }
 
     return FAIL;
 }