vim-patch:8.1.1563: crash when using closures

Problem:    Crash when using closures.
Solution:   Set reference in varlist of funccal when running the garbage
            collector. (Ozaki Kiichi, closes vim/vim#4554, closes vim/vim#4547)
6e5000d493
This commit is contained in:
erw7
2019-09-08 11:04:37 +09:00
committed by Jan Edmund Lazo
parent 3430e40c60
commit 7cb38d5ac4
2 changed files with 23 additions and 6 deletions

View File

@@ -3347,9 +3347,13 @@ bool set_ref_in_previous_funccal(int copyID)
{ {
bool abort = false; bool abort = false;
for (funccall_T *fc = previous_funccal; fc != NULL; fc = fc->caller) { for (funccall_T *fc = previous_funccal; !abort && fc != NULL;
abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1, NULL); fc = fc->caller) {
abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1, NULL); fc->fc_copyID = copyID + 1;
abort = abort
|| set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1, NULL)
|| set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1, NULL)
|| set_ref_in_list(&fc->l_varlist, copyID + 1, NULL);
} }
return abort; return abort;
} }
@@ -3360,9 +3364,11 @@ static bool set_ref_in_funccal(funccall_T *fc, int copyID)
if (fc->fc_copyID != copyID) { if (fc->fc_copyID != copyID) {
fc->fc_copyID = copyID; fc->fc_copyID = copyID;
abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL); abort = abort
abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL); || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL)
abort = abort || set_ref_in_func(NULL, fc->func, copyID); || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL)
|| set_ref_in_list(&fc->l_varlist, copyID, NULL)
|| set_ref_in_func(NULL, fc->func, copyID);
} }
return abort; return abort;
} }

View File

@@ -1409,6 +1409,17 @@ func Test_compound_assignment_operators()
let @/ = '' let @/ = ''
endfunc endfunc
func! Test_funccall_garbage_collect()
func Func(x, ...)
call add(a:x, a:000)
endfunc
call Func([], [])
" Must not crash cause by invalid freeing
call test_garbagecollect_now()
call assert_true(v:true)
delfunc Func
endfunc
func Test_function_defined_line() func Test_function_defined_line()
if has('gui_running') if has('gui_running')
" Can't catch the output of gvim. " Can't catch the output of gvim.