changeset 33501:c7c630759e31 v9.0.2000

patch 9.0.2000: Vim9: use-after-free in deep call stack Commit: https://github.com/vim/vim/commit/1087b8c29ab521106c5b6cc85d5b38244f0d9c1d Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Sat Oct 7 22:03:18 2023 +0200 patch 9.0.2000: Vim9: use-after-free in deep call stack Problem: Vim9: use-after-free in deep call stack Solution: Get the objct pointer from execution stack closes: #13296 Signed-off-by: Christian Brabandt <cb@256bit.org> Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
author Christian Brabandt <cb@256bit.org>
date Sat, 07 Oct 2023 22:15:07 +0200
parents 665078e8fea1
children 4c2e97be0fbe
files src/testdir/test_vim9_class.vim src/version.c src/vim9execute.c
diffstat 3 files changed, 48 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -6989,4 +6989,44 @@ func Test_object_variable_complex_type_c
   call v9.CheckSourceSuccess(lines)
 endfunc
 
+" Test for recursively calling an object method.  This used to cause an
+" use-after-free error.
+def Test_recursive_object_method_call()
+  var lines =<< trim END
+    vim9script
+    class A
+      this.val: number = 0
+      def Foo(): number
+        if this.val >= 90
+          return this.val
+        endif
+        this.val += 1
+        return this.Foo()
+      enddef
+    endclass
+    var a = A.new()
+    assert_equal(90, a.Foo())
+  END
+  v9.CheckSourceSuccess(lines)
+enddef
+
+" Test for recursively calling a class method.
+def Test_recursive_class_method_call()
+  var lines =<< trim END
+    vim9script
+    class A
+      static val: number = 0
+      static def Foo(): number
+        if val >= 90
+          return val
+        endif
+        val += 1
+        return Foo()
+      enddef
+    endclass
+    assert_equal(90, A.Foo())
+  END
+  v9.CheckSourceSuccess(lines)
+enddef
+
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2000,
+/**/
     1999,
 /**/
     1998,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -559,6 +559,12 @@ call_dfunc(
 				     arg_to_add + STACK_FRAME_SIZE + varcount))
 	return FAIL;
 
+    // The object pointer is in the execution typval stack.  The GA_GROW call
+    // above may have reallocated the execution typval stack.  So the object
+    // pointer may not be valid anymore.  Get the object pointer again from the
+    // execution stack.
+    obj = STACK_TV_BOT(0) - argcount - vararg_count - 1;
+
     // If depth of calling is getting too high, don't execute the function.
     if (funcdepth_increment() == FAIL)
 	return FAIL;