changeset 34769:d4fb6ea26ae4 v9.1.0261

patch 9.1.0261: Vim9: protected class and funcrefs accessible outside the class Commit: https://github.com/vim/vim/commit/3e33650b3a9939f6b942c1d1eccdb261ea17a647 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Thu Apr 4 19:35:59 2024 +0200 patch 9.1.0261: Vim9: protected class and funcrefs accessible outside the class Problem: Vim9: protected class and funcrefs accessible outside the class (Aliaksei Budavei) Solution: Check if class and object funcrefs are protected (Yegappan) closes: #14407 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Thu, 04 Apr 2024 19:45:10 +0200
parents 1faaf5fdbb06
children f03486fc4b8c
files src/testdir/test_functions.vim src/testdir/test_vim9_class.vim src/userfunc.c src/version.c src/vim9class.c
diffstat 5 files changed, 80 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_functions.vim
+++ b/src/testdir/test_functions.vim
@@ -3794,6 +3794,43 @@ func Test_funcref_to_string()
   call assert_equal("function('g:Test_funcref_to_string')", string(Fn))
 endfunc
 
+" A funcref cannot start with an underscore (except when used as a protected
+" class or object variable)
+func Test_funcref_with_underscore()
+  " at script level
+  let lines =<< trim END
+    vim9script
+    var _Fn = () => 10
+  END
+  call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Fn')
+
+  " inside a function
+  let lines =<< trim END
+    vim9script
+    def Func()
+      var _Fn = () => 10
+    enddef
+    defcompile
+  END
+  call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Fn', 1)
+
+  " as a function argument
+  let lines =<< trim END
+    vim9script
+    def Func(_Fn: func)
+    enddef
+    defcompile
+  END
+  call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Fn', 2)
+
+  " as a lambda argument
+  let lines =<< trim END
+    vim9script
+    var Fn = (_Farg: func) => 10
+  END
+  call v9.CheckSourceFailure(lines, 'E704: Funcref variable name must start with a capital: _Farg', 2)
+endfunc
+
 " Test for isabsolutepath()
 func Test_isabsolutepath()
   call assert_false(isabsolutepath(''))
--- a/src/testdir/test_vim9_class.vim
+++ b/src/testdir/test_vim9_class.vim
@@ -10530,4 +10530,27 @@ def Test_use_base_class_variable_from_ba
   v9.CheckScriptSuccess(lines)
 enddef
 
+" Test for accessing protected funcref object and class variables
+def Test_protected_funcref()
+  # protected funcref object variable
+  var lines =<< trim END
+    vim9script
+    class Test1
+      const _Id: func(any): any = (v) => v
+    endclass
+    var n = Test1.new()._Id(1)
+  END
+  v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test1"', 5)
+
+  # protected funcref class variable
+  lines =<< trim END
+    vim9script
+    class Test2
+      static const _Id: func(any): any = (v) => v
+    endclass
+    var n = Test2._Id(2)
+  END
+  v9.CheckScriptFailure(lines, 'E1333: Cannot access protected variable "_Id" in class "Test2"', 5)
+enddef
+
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -570,10 +570,16 @@ parse_argument_types(
 		fp->uf_arg_types[i] = type;
 		if (i < fp->uf_args.ga_len
 			&& (type->tt_type == VAR_FUNC
-			    || type->tt_type == VAR_PARTIAL)
-			&& var_wrong_func_name(
-				    ((char_u **)fp->uf_args.ga_data)[i], TRUE))
-		    return FAIL;
+			    || type->tt_type == VAR_PARTIAL))
+		{
+		    char_u *name = ((char_u **)fp->uf_args.ga_data)[i];
+		    if (obj_members != NULL && *name == '_')
+			// protected object method
+			name++;
+
+		    if (var_wrong_func_name(name, TRUE))
+			return FAIL;
+		}
 	    }
 	}
     }
--- 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 */
 /**/
+    261,
+/**/
     260,
 /**/
     259,
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -2835,6 +2835,14 @@ call_oc_method(
 	    return FAIL;
 	}
 
+	if (*name == '_')
+	{
+	    // Protected object or class funcref variable
+	    semsg(_(e_cannot_access_protected_variable_str), ocm->ocm_name,
+		    cl->class_name);
+	    return FAIL;
+	}
+
 	if (rettv->v_type == VAR_OBJECT)
 	{
 	    // funcref object variable