aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorerw7 <erw7.github@gmail.com>2019-09-08 11:04:37 +0900
committerJan Edmund Lazo <jan.lazo@mail.utoronto.ca>2020-09-30 21:00:17 -0400
commit7cb38d5ac41efc1dce80a2e40c9c55f8a3802d61 (patch)
tree3fc3b77b2536a701e4efa334ef27a3a5a4a4d2b8
parent3430e40c609ff29e7fce52f017361583c380f46b (diff)
downloadrneovim-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
-rw-r--r--src/nvim/eval/userfunc.c18
-rw-r--r--src/nvim/testdir/test_vimscript.vim11
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.