]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.2002: Vim9: heap-use-after-free when when accessing protect class member v9.1.2002
authorYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 21 Dec 2025 19:03:31 +0000 (19:03 +0000)
committerChristian Brabandt <cb@256bit.org>
Sun, 21 Dec 2025 19:03:31 +0000 (19:03 +0000)
Problem:  Vim9: heap-use-after-free when when accessing protect class
          member (Foxe Chen)
Solution: Set cl->class_type_list and return directly, add tests for
          using protected class method and variable from another class
          (Yegappan Lakshmanan).

closes: #18971

Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
src/testdir/test_vim9_class.vim
src/version.c
src/vim9class.c

index 6ec7ffa6e232288474f13a3d76c5e810f79be6b8..d0260c202c122a1b53a8303425e307854885a2c3 100644 (file)
@@ -5245,7 +5245,7 @@ def Test_lockvar_islocked_notfound()
 enddef
 
 " Test for a protected object method
-def Test_private_object_method()
+def Test_protected_object_method()
   # Try calling a protected method using an object (at the script level)
   var lines =<< trim END
     vim9script
@@ -5482,10 +5482,27 @@ def Test_private_object_method()
     var a = _Foo()
   END
   v9.CheckSourceFailure(lines, 'E1267: Function name must start with a capital: _Foo(): number', 2)
+
+  # Test for initializing a protected funcref instance variable to a protected
+  # class method from another class
+  lines =<< trim END
+    vim9script
+
+    class A
+      static def _Internal(): string
+      enddef
+    endclass
+
+    class B
+      var Fn: func = A._Internal
+    endclass
+    var b = B.new()
+  END
+  v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Internal', 1)
 enddef
 
 " Test for an protected class method
-def Test_private_class_method()
+def Test_protected_class_method()
   # Try calling a class protected method (at the script level)
   var lines =<< trim END
     vim9script
@@ -5680,6 +5697,22 @@ def Test_private_class_method()
     assert_equal(1234, C._Foo())
   END
   v9.CheckSourceFailure(lines, 'E1325: Method "_Foo" not found in class "C"', 16)
+
+  # Test for initializing a protected funcref class variable to a protected
+  # class method from another class
+  lines =<< trim END
+    vim9script
+
+    class A
+      static def _Internal(): string
+      enddef
+    endclass
+
+    class B
+      static var Fn: func = A._Internal
+    endclass
+  END
+  v9.CheckSourceFailure(lines, 'E1366: Cannot access protected method: _Internal', 10)
 enddef
 
 " Test for using the return value of a class/object method as a function
@@ -5938,15 +5971,12 @@ def Test_dup_member_variable()
 enddef
 
 " Test for accessing a protected member outside a class in a def function
-def Test_private_member_access_outside_class()
-  # protected object member variable
+def Test_protected_member_access_outside_class()
+  # try to modify a protected instance variable from a def function
   var lines =<< trim END
     vim9script
     class A
       var _val = 10
-      def GetVal(): number
-        return this._val
-      enddef
     endclass
     def T()
       var a = A.new()
@@ -5956,7 +5986,7 @@ def Test_private_member_access_outside_class()
   END
   v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 2)
 
-  # access a non-existing protected object member variable
+  # access a non-existing protected instance variable from a def function
   lines =<< trim END
     vim9script
     class A
@@ -5970,7 +6000,7 @@ def Test_private_member_access_outside_class()
   END
   v9.CheckSourceFailure(lines, 'E1326: Variable "_a" not found in object "A"', 2)
 
-  # protected static member variable
+  # try to read a protected class variable from a def function using an instance
   lines =<< trim END
     vim9script
     class A
@@ -5984,7 +6014,8 @@ def Test_private_member_access_outside_class()
   END
   v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
 
-  # protected static member variable
+  # try to modify a protected class variable from a def function using an
+  # instance
   lines =<< trim END
     vim9script
     class A
@@ -5998,7 +6029,7 @@ def Test_private_member_access_outside_class()
   END
   v9.CheckSourceFailure(lines, 'E1375: Class variable "_val" accessible only using class "A"', 2)
 
-  # protected static class variable
+  # try to read a protected class variable from a def function using the class
   lines =<< trim END
     vim9script
     class A
@@ -6011,7 +6042,7 @@ def Test_private_member_access_outside_class()
   END
   v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
 
-  # protected static class variable
+  # try to modify a protected class variable from a def function using the class
   lines =<< trim END
     vim9script
     class A
@@ -6023,6 +6054,33 @@ def Test_private_member_access_outside_class()
     T()
   END
   v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_val" in class "A"', 1)
+
+  # initialize a protected class variable using a protected class variable
+  # from another class
+  lines =<< trim END
+    vim9script
+    class A
+      static var _aval = 10
+    endclass
+    class B
+      static var _bval = A._aval
+    endclass
+  END
+  v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_aval" in class "A"', 7)
+
+  # initialize a protected instance variable using a protected class variable
+  # from another class
+  lines =<< trim END
+    vim9script
+    class A
+      static var _aval = 10
+    endclass
+    class B
+      var _bval = A._aval
+    endclass
+    var b = B.new()
+  END
+  v9.CheckSourceFailure(lines, 'E1333: Cannot access protected variable "_aval" in class "A"', 1)
 enddef
 
 " Test for changing the member access of an interface in a implementation class
@@ -7088,7 +7146,7 @@ def Test_extend_empty_class()
   v9.CheckSourceSuccess(lines)
 enddef
 
-" A interface cannot have a static variable or a static method or a private
+" A interface cannot have a static variable or a static method or a protected
 " variable or a protected method or a public variable
 def Test_interface_with_unsupported_members()
   var lines =<< trim END
@@ -11686,7 +11744,7 @@ def Test_any_obj_var_type()
   END
   v9.CheckScriptSuccess(lines)
 
-  # Modifying an object private variable from a method in another class using
+  # Modifying an object protected variable from a method in another class using
   # any type
   lines =<< trim END
     vim9script
@@ -11756,7 +11814,7 @@ def Test_any_obj_var_type()
   END
   v9.CheckScriptSuccess(lines)
 
-  # Try to modify a private object variable using a variable of type "any"
+  # Try to modify a protected object variable using a variable of type "any"
   lines =<< trim END
     vim9script
 
index a8602f71b25d3eab8b7e4d088343a3f6c780ba86..534d365e584307a3ecb6e532527b681ae855a9bd 100644 (file)
@@ -734,6 +734,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2002,
 /**/
     2001,
 /**/
index ea91706f06d6083bb31bf95051046161ba368f9d..e5b811b91541632dcb1d556719bacfa8a489a473 100644 (file)
@@ -2700,7 +2700,10 @@ early_ret:
        // Allocate a typval for each class member and initialize it.
        if ((is_class || is_enum) && cl->class_class_member_count > 0)
            if (add_class_members(cl, eap, &type_list) == FAIL)
-               goto cleanup;
+           {
+               cl->class_type_list = type_list;
+               return;
+           }
 
        cl->class_type_list = type_list;