Mercurial > vim
changeset 33167:13258b342d38 v9.0.1865
patch 9.0.1865: Vim9: garbage collection may cause crash
Commit: https://github.com/vim/vim/commit/544be0d893e68c494aed09232d5bee4ca8b74619
Author: Yegappan Lakshmanan <yegappan@yahoo.com>
Date: Mon Sep 4 22:14:28 2023 +0200
patch 9.0.1865: Vim9: garbage collection may cause crash
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>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Mon, 04 Sep 2023 22:30:03 +0200 |
parents | 13914615534e |
children | af4d720e413b |
files | src/eval.c src/testdir/test_vim9_class.vim src/version.c |
diffstat | 3 files changed, 65 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- 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,
--- 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