From e798446362efe4d784a26f51b106280d35c6da82 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Tue, 12 Nov 2024 21:03:00 +0100 Subject: [PATCH] patch 9.1.0861: Vim9: no runtime check for object member access of any var Problem: Vim9: no runtime check for object member access of any var (after: 9.1.0850) Solution: Add runtime type compatibility check for object member accessed using a any variable (Yegappan Lakshmanan). closes: #16037 Signed-off-by: Yegappan Lakshmanan Signed-off-by: Christian Brabandt --- src/testdir/test_vim9_class.vim | 48 +++++++++++++++++++++++++++++++++ src/version.c | 2 ++ src/vim9execute.c | 7 +++++ 3 files changed, 57 insertions(+) diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim index 4ce9fcdc49..d8a3fa383f 100644 --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -11546,6 +11546,54 @@ def Test_any_obj_var_type() Fn(null_object) END v9.CheckScriptFailure(lines, 'E1360: Using a null object', 1) + + # Try to change a const object variable using a "any" variable + lines =<< trim END + vim9script + class A + public const v1: number = 123 + endclass + + def Fn(o: any) + o.v1 = 321 + enddef + + var a = A.new() + Fn(a) + END + v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1) + + # Try to change a final object variable using a "any" variable + lines =<< trim END + vim9script + class A + public final v1: number = 123 + endclass + + def Fn(o: any) + o.v1 = 321 + enddef + + var a = A.new() + Fn(a) + END + v9.CheckScriptFailure(lines, 'E1409: Cannot change read-only variable "v1" in class "A"', 1) + + # Assign a different type of value to an "any" type object variable + lines =<< trim END + vim9script + class A + public var v1: list = [1, 2] + endclass + + def Fn(o: A) + o.v1 = 'abc' + enddef + + var a = A.new() + Fn(a) + END + v9.CheckScriptFailure(lines, 'E1012: Type mismatch; expected list but got string', 1) enddef " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index 7985985689..f2e9473f7e 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 861, /**/ 860, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index da03d5e7d4..7ab6813a69 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -2271,6 +2271,7 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx) // Get the current function ufunc_T *ufunc = (((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx)->df_ufunc; + where_T where = WHERE_INIT; // Check whether the member variable is writeable if ((m->ocm_access != VIM_ACCESS_ALL) && @@ -2283,6 +2284,12 @@ execute_storeindex(isn_T *iptr, ectx_T *ectx) emsg_var_cl_define(msg, m->ocm_name, 0, cl); status = FAIL; } + // Fail if the variable is a const or final or the type + // is not compatible + else if (oc_var_check_ro(cl, m) || + check_typval_type(m->ocm_type, tv, where) + == FAIL) + status = FAIL; else lidx = m_idx; }