diff options
author | erw7 <erw7.github@gmail.com> | 2019-09-08 11:04:37 +0900 |
---|---|---|
committer | Jan Edmund Lazo <jan.lazo@mail.utoronto.ca> | 2020-09-30 21:00:17 -0400 |
commit | 7cb38d5ac41efc1dce80a2e40c9c55f8a3802d61 (patch) | |
tree | 3fc3b77b2536a701e4efa334ef27a3a5a4a4d2b8 /src | |
parent | 3430e40c609ff29e7fce52f017361583c380f46b (diff) | |
download | rneovim-7cb38d5ac41efc1dce80a2e40c9c55f8a3802d61.tar.gz rneovim-7cb38d5ac41efc1dce80a2e40c9c55f8a3802d61.tar.bz2 rneovim-7cb38d5ac41efc1dce80a2e40c9c55f8a3802d61.zip |
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)
https://github.com/vim/vim/commit/6e5000d493b4f385f901eb97f3ce0c8088373403
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/eval/userfunc.c | 18 | ||||
-rw-r--r-- | src/nvim/testdir/test_vimscript.vim | 11 |
2 files changed, 23 insertions, 6 deletions
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 1b80b22213..d5a19dd7b9 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3347,9 +3347,13 @@ bool set_ref_in_previous_funccal(int copyID) { bool abort = false; - for (funccall_T *fc = previous_funccal; fc != NULL; fc = fc->caller) { - abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1, NULL); - abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1, NULL); + for (funccall_T *fc = previous_funccal; !abort && fc != NULL; + fc = fc->caller) { + 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; } @@ -3360,9 +3364,11 @@ static bool set_ref_in_funccal(funccall_T *fc, int copyID) if (fc->fc_copyID != copyID) { fc->fc_copyID = copyID; - abort = abort || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL); - abort = abort || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL); - abort = abort || set_ref_in_func(NULL, fc->func, copyID); + abort = abort + || set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL) + || 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; } diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim index d2f13ff072..3e2e1795dc 100644 --- a/src/nvim/testdir/test_vimscript.vim +++ b/src/nvim/testdir/test_vimscript.vim @@ -1409,6 +1409,17 @@ func Test_compound_assignment_operators() let @/ = '' 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() if has('gui_running') " Can't catch the output of gvim. |