changeset 27565:0b12dd90a5d6 v8.2.4309

patch 8.2.4309: Vim9: crash when using a partial in the wrong context Commit: https://github.com/vim/vim/commit/fe1bfc9b267fffedac6b5224d7aa6cc5d9d15f64 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Feb 6 13:55:03 2022 +0000 patch 8.2.4309: Vim9: crash when using a partial in the wrong context Problem: Vim9: crash when using a partial in the wrong context. Solution: Don't use an NULL outer pointer. (closes https://github.com/vim/vim/issues/9706)
author Bram Moolenaar <Bram@vim.org>
date Sun, 06 Feb 2022 15:00:03 +0100
parents b7040a16ebb1
children 9f46667ef05f
files src/testdir/test_vim9_func.vim src/version.c src/vim9execute.c
diffstat 3 files changed, 40 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_func.vim
+++ b/src/testdir/test_vim9_func.vim
@@ -3125,6 +3125,35 @@ def Test_partial_call()
   v9.CheckScriptFailure(lines, 'E1235:')
 enddef
 
+" Using "idx" from a legacy global function does not work.
+" This caused a crash when called from legacy context.
+func Test_partial_call_fails()
+  let lines =<< trim END
+      vim9script
+
+      var l = ['a', 'b', 'c']
+      def Iter(container: any): any
+        var idx = -1
+        var obj = {state: container}
+        def g:__NextItem__(self: dict<any>): any
+          ++idx
+          return self.state[idx]
+        enddef
+        obj.__next__ = function('g:__NextItem__', [obj])
+        return obj
+      enddef
+
+      var it = Iter(l)
+      echo it.__next__()
+  END
+  call writefile(lines, 'XpartialCall')
+  try
+    source XpartialCall
+  catch /E1248:/
+  endtry
+  call delete('XpartialCall')
+endfunc
+
 def Test_cmd_modifier()
   tab echo '0'
   v9.CheckDefFailure(['5tab echo 3'], 'E16:')
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4309,
+/**/
     4308,
 /**/
     4307,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1694,7 +1694,7 @@ handle_debug(isn_T *iptr, ectx_T *ectx)
 }
 
 /*
- * Store a value in a list or dict variable.
+ * Store a value in a list, dict or blob variable.
  * Returns OK, FAIL or NOTDONE (uncatchable error).
  */
     static int
@@ -5081,12 +5081,16 @@ call_def_function(
 		goto failed_early;
 	    if (partial != NULL)
 	    {
-		if (partial->pt_outer.out_stack == NULL && current_ectx != NULL)
+		if (partial->pt_outer.out_stack == NULL)
 		{
-		    if (current_ectx->ec_outer_ref != NULL
-			    && current_ectx->ec_outer_ref->or_outer != NULL)
-			ectx.ec_outer_ref->or_outer =
+		    if (current_ectx != NULL)
+		    {
+			if (current_ectx->ec_outer_ref != NULL
+			       && current_ectx->ec_outer_ref->or_outer != NULL)
+			    ectx.ec_outer_ref->or_outer =
 					  current_ectx->ec_outer_ref->or_outer;
+		    }
+		    // Should there be an error here?
 		}
 		else
 		{