diff options
author | Yegappan Lakshmanan <yegappan@yahoo.com> | 2023-09-04 22:14:28 +0200 |
---|---|---|
committer | Christian Brabandt <cb@256bit.org> | 2023-09-04 22:14:28 +0200 |
commit | 544be0d893e68c494aed09232d5bee4ca8b74619 (patch) | |
tree | 572489199caca04b829c88bc8faf764c8c0a2184 | |
parent | 623ba31821a41acee7e948794e84867680b97885 (diff) |
patch 9.0.1865: Vim9: garbage collection may cause crashv9.0.1865
Problem: Vim9: garbage collection may cause crash
Solution: validate that class members typeval is not null
closes: #13028
Signed-off-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
-rw-r--r-- | src/eval.c | 13 | ||||
-rw-r--r-- | src/testdir/test_vim9_class.vim | 54 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 65 insertions, 4 deletions
diff --git a/src/eval.c b/src/eval.c index 4143dd2ac6..7cfe68cc66 100644 --- a/src/eval.c +++ b/src/eval.c @@ -5725,10 +5725,15 @@ set_ref_in_item_class( return FALSE; cl->class_copyID = copyID; - for (int i = 0; !abort && i < cl->class_class_member_count; ++i) - abort = abort || set_ref_in_item( - &cl->class_members_tv[i], - copyID, ht_stack, list_stack); + if (cl->class_members_tv != NULL) + { + // The "class_members_tv" table is allocated only for regular classes + // and not for interfaces. + for (int i = 0; !abort && i < cl->class_class_member_count; ++i) + abort = abort || set_ref_in_item( + &cl->class_members_tv[i], + copyID, ht_stack, list_stack); + } for (int i = 0; !abort && i < cl->class_class_function_count; ++i) abort = abort || set_ref_in_func(NULL, diff --git a/src/testdir/test_vim9_class.vim b/src/testdir/test_vim9_class.vim index 72cdaf086c..8ae136f283 100644 --- a/src/testdir/test_vim9_class.vim +++ b/src/testdir/test_vim9_class.vim @@ -1307,6 +1307,60 @@ func Test_class_garbagecollect() call v9.CheckScriptSuccess(lines) endfunc +" Test interface garbage collection +func Test_interface_garbagecollect() + let lines =<< trim END + vim9script + + interface I + static ro_class_var: number + public static rw_class_var: number + static _priv_class_var: number + this.ro_obj_var: number + public this.rw_obj_var: number + this._priv_obj_var: number + + static def ClassFoo(): number + static def _ClassBar(): number + def ObjFoo(): number + def _ObjBar(): number + endinterface + + class A implements I + static ro_class_var: number = 10 + public static rw_class_var: number = 20 + static _priv_class_var: number = 30 + this.ro_obj_var: number = 40 + public this.rw_obj_var: number = 50 + this._priv_obj_var: number = 60 + + static def _ClassBar(): number + return _priv_class_var + enddef + + static def ClassFoo(): number + return ro_class_var + rw_class_var + A._ClassBar() + enddef + + def _ObjBar(): number + return this._priv_obj_var + enddef + + def ObjFoo(): number + return this.ro_obj_var + this.rw_obj_var + this._ObjBar() + enddef + endclass + + assert_equal(60, A.ClassFoo()) + var o = A.new() + assert_equal(150, o.ObjFoo()) + test_garbagecollect_now() + assert_equal(60, A.ClassFoo()) + assert_equal(150, o.ObjFoo()) + END + call v9.CheckScriptSuccess(lines) +endfunc + def Test_class_function() var lines =<< trim END vim9script diff --git a/src/version.c b/src/version.c index c2faee46cc..c4b793f506 100644 --- a/src/version.c +++ b/src/version.c @@ -700,6 +700,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1865, +/**/ 1864, /**/ 1863, |