changeset 31521:065e4ccf5e10 v9.0.1093

patch 9.0.1093: using freed memory of object member Commit: https://github.com/vim/vim/commit/590162cae0410b50572a3ab0e72a2e5873b99f1a Author: Bram Moolenaar <Bram@vim.org> Date: Sat Dec 24 21:24:06 2022 +0000 patch 9.0.1093: using freed memory of object member Problem: Using freed memory of object member. (Yegappan Lakshmanan) Solution: Make a copy of the object member when getting it.
author Bram Moolenaar <Bram@vim.org>
date Sat, 24 Dec 2022 22:30:03 +0100
parents f745a88f5d62
children c671c97b18ed
files src/testdir/test_vim9_class.vim src/version.c src/vim9execute.c
diffstat 3 files changed, 30 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -323,6 +323,32 @@ def Test_class_object_member_access()
       assert_fails('trip.four = 4', 'E1334')
   END
   v9.CheckScriptSuccess(lines)
+
+  lines =<< trim END
+      vim9script
+
+      class MyCar
+        this.make: string
+
+        def new(make_arg: string)
+          this.make = make_arg
+        enddef
+
+        def GetMake(): string
+          return $"make = {this.make}"
+        enddef
+      endclass
+
+      var c = MyCar.new("abc")
+      assert_equal('make = abc', c.GetMake())
+
+      c = MyCar.new("def")
+      assert_equal('make = def', c.GetMake())
+
+      var c2 = MyCar.new("123")
+      assert_equal('make = 123', c2.GetMake())
+  END
+  v9.CheckScriptSuccess(lines)
 enddef
 
 def Test_class_member_access()
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1093,
+/**/
     1092,
 /**/
     1091,
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -3799,7 +3799,7 @@ exec_instructions(ectx_T *ectx)
 		tv->vval.v_number = iptr->isn_arg.storenr.stnr_val;
 		break;
 
-	    // store value in list or dict variable
+	    // Store a value in a list, dict, blob or object variable.
 	    case ISN_STOREINDEX:
 		{
 		    int res = execute_storeindex(iptr, ectx);
@@ -5159,7 +5159,7 @@ exec_instructions(ectx_T *ectx)
 		    object_T *obj = tv->vval.v_object;
 		    // the members are located right after the object struct
 		    typval_T *mtv = ((typval_T *)(obj + 1)) + idx;
-		    *tv = *mtv;
+		    copy_tv(mtv, tv);
 
 		    // Unreference the object after getting the member, it may
 		    // be freed.