Skip to content

Commit 6ae8fae

Browse files
yegappanbrammool
authored andcommitted
patch 8.2.3788: lambda for option that is a function may be freed
Problem: Lambda for option that is a function may be garbage collected. Solution: Set a reference in the funcref. (Yegappan Lakshmanan, closes #9330)
1 parent 6e371ec commit 6ae8fae

19 files changed

Lines changed: 1091 additions & 898 deletions

src/eval.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4516,6 +4516,18 @@ garbage_collect(int testing)
45164516
// callbacks in buffers
45174517
abort = abort || set_ref_in_buffers(copyID);
45184518

4519+
// 'completefunc', 'omnifunc' and 'thesaurusfunc' callbacks
4520+
abort = abort || set_ref_in_insexpand_funcs(copyID);
4521+
4522+
// 'operatorfunc' callback
4523+
abort = abort || set_ref_in_opfunc(copyID);
4524+
4525+
// 'tagfunc' callback
4526+
abort = abort || set_ref_in_tagfunc(copyID);
4527+
4528+
// 'imactivatefunc' and 'imstatusfunc' callbacks
4529+
abort = abort || set_ref_in_im_funcs(copyID);
4530+
45194531
#ifdef FEAT_LUA
45204532
abort = abort || set_ref_in_lua(copyID);
45214533
#endif
@@ -4743,6 +4755,22 @@ set_ref_in_list_items(list_T *l, int copyID, ht_stack_T **ht_stack)
47434755
return abort;
47444756
}
47454757

4758+
/*
4759+
* Mark the partial in callback 'cb' with "copyID".
4760+
*/
4761+
int
4762+
set_ref_in_callback(callback_T *cb, int copyID)
4763+
{
4764+
typval_T tv;
4765+
4766+
if (cb->cb_name == NULL || *cb->cb_name == NUL || cb->cb_partial == NULL)
4767+
return FALSE;
4768+
4769+
tv.v_type = VAR_PARTIAL;
4770+
tv.vval.v_partial = cb->cb_partial;
4771+
return set_ref_in_item(&tv, copyID, NULL, NULL);
4772+
}
4773+
47464774
/*
47474775
* Mark all lists and dicts referenced through typval "tv" with "copyID".
47484776
* "list_stack" is used to add lists to be marked. Can be NULL.

src/evalbuffer.c

Lines changed: 15 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,31 +26,25 @@ set_ref_in_buffers(int copyID)
2626
FOR_ALL_BUFFERS(bp)
2727
{
2828
listener_T *lnr;
29-
typval_T tv;
3029

3130
for (lnr = bp->b_listener; !abort && lnr != NULL; lnr = lnr->lr_next)
32-
{
33-
if (lnr->lr_callback.cb_partial != NULL)
34-
{
35-
tv.v_type = VAR_PARTIAL;
36-
tv.vval.v_partial = lnr->lr_callback.cb_partial;
37-
abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
38-
}
39-
}
31+
abort = abort || set_ref_in_callback(&lnr->lr_callback, copyID);
4032
# ifdef FEAT_JOB_CHANNEL
41-
if (!abort && bp->b_prompt_callback.cb_partial != NULL)
42-
{
43-
tv.v_type = VAR_PARTIAL;
44-
tv.vval.v_partial = bp->b_prompt_callback.cb_partial;
45-
abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
46-
}
47-
if (!abort && bp->b_prompt_interrupt.cb_partial != NULL)
48-
{
49-
tv.v_type = VAR_PARTIAL;
50-
tv.vval.v_partial = bp->b_prompt_interrupt.cb_partial;
51-
abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL);
52-
}
33+
if (!abort)
34+
abort = abort || set_ref_in_callback(&bp->b_prompt_callback, copyID);
35+
if (!abort)
36+
abort = abort || set_ref_in_callback(&bp->b_prompt_interrupt, copyID);
5337
# endif
38+
#ifdef FEAT_COMPL_FUNC
39+
if (!abort)
40+
abort = abort || set_ref_in_callback(&bp->b_cfu_cb, copyID);
41+
if (!abort)
42+
abort = abort || set_ref_in_callback(&bp->b_ofu_cb, copyID);
43+
if (!abort)
44+
abort = abort || set_ref_in_callback(&bp->b_tsrfu_cb, copyID);
45+
#endif
46+
if (!abort)
47+
abort = abort || set_ref_in_callback(&bp->b_tfu_cb, copyID);
5448
if (abort)
5549
break;
5650
}

src/evalvars.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1395,7 +1395,6 @@ ex_let_option(
13951395
char_u *tofree = NULL;
13961396
char_u numbuf[NUMBUFLEN];
13971397

1398-
13991398
c1 = *p;
14001399
*p = NUL;
14011400

src/gui_xim.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,32 @@ call_imstatusfunc(void)
117117
void
118118
free_xim_stuff(void)
119119
{
120-
#if defined(FEAT_EVAL) && \
120+
# if defined(FEAT_EVAL) && \
121121
(defined(FEAT_XIM) || defined(IME_WITHOUT_XIM) || defined(VIMDLL))
122122
free_callback(&imaf_cb);
123123
free_callback(&imsf_cb);
124124
# endif
125125
}
126126
#endif
127127

128+
/*
129+
* Mark the global 'imactivatefunc' and 'imstatusfunc' callbacks with 'copyID'
130+
* so that they are not garbage collected.
131+
*/
132+
int
133+
set_ref_in_im_funcs(int copyID UNUSED)
134+
{
135+
int abort = FALSE;
136+
137+
#if defined(FEAT_EVAL) && \
138+
(defined(FEAT_XIM) || defined(IME_WITHOUT_XIM) || defined(VIMDLL))
139+
abort = set_ref_in_callback(&imaf_cb, copyID);
140+
abort = abort || set_ref_in_callback(&imsf_cb, copyID);
141+
#endif
142+
143+
return abort;
144+
}
145+
128146

129147
#if defined(FEAT_XIM) || defined(PROTO)
130148

src/insexpand.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2341,6 +2341,21 @@ set_thesaurusfunc_option(void)
23412341
return retval;
23422342
}
23432343

2344+
/*
2345+
* Mark the global 'completefunc' 'omnifunc' and 'thesaurusfunc' callbacks with
2346+
* 'copyID' so that they are not garbage collected.
2347+
*/
2348+
int
2349+
set_ref_in_insexpand_funcs(int copyID)
2350+
{
2351+
int abort = FALSE;
2352+
2353+
abort = set_ref_in_callback(&cfu_cb, copyID);
2354+
abort = abort || set_ref_in_callback(&ofu_cb, copyID);
2355+
abort = abort || set_ref_in_callback(&tsrfu_cb, copyID);
2356+
2357+
return abort;
2358+
}
23442359

23452360
/*
23462361
* Get the user-defined completion function name for completion 'type'

src/ops.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3341,12 +3341,28 @@ set_operatorfunc_option(void)
33413341
void
33423342
free_operatorfunc_option(void)
33433343
{
3344-
# ifdef FEAT_EVAL
3344+
# ifdef FEAT_EVAL
33453345
free_callback(&opfunc_cb);
3346-
# endif
3346+
# endif
33473347
}
33483348
#endif
33493349

3350+
/*
3351+
* Mark the global 'operatorfunc' callback with 'copyID' so that it is not
3352+
* garbage collected.
3353+
*/
3354+
int
3355+
set_ref_in_opfunc(int copyID UNUSED)
3356+
{
3357+
int abort = FALSE;
3358+
3359+
#ifdef FEAT_EVAL
3360+
abort = set_ref_in_callback(&opfunc_cb, copyID);
3361+
#endif
3362+
3363+
return abort;
3364+
}
3365+
33503366
/*
33513367
* Handle the "g@" operator: call 'operatorfunc'.
33523368
*/

src/proto/eval.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ int set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack);
5252
int set_ref_in_dict(dict_T *d, int copyID);
5353
int set_ref_in_list(list_T *ll, int copyID);
5454
int set_ref_in_list_items(list_T *l, int copyID, ht_stack_T **ht_stack);
55+
int set_ref_in_callback(callback_T *cb, int copyID);
5556
int set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack_T **list_stack);
5657
char_u *echo_string_core(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID, int echo_style, int restore_copyID, int composite_val);
5758
char_u *echo_string(typval_T *tv, char_u **tofree, char_u *numbuf, int copyID);

src/proto/gui_xim.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
int set_imactivatefunc_option(void);
33
int set_imstatusfunc_option(void);
44
void free_xim_stuff(void);
5+
int set_ref_in_im_funcs(int copyID);
56
void im_set_active(int active);
67
void xim_set_focus(int focus);
78
void im_set_position(int row, int col);

src/proto/insexpand.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ void set_buflocal_cfu_callback(buf_T *buf);
4444
int set_omnifunc_option(void);
4545
void set_buflocal_ofu_callback(buf_T *buf);
4646
int set_thesaurusfunc_option(void);
47+
int set_ref_in_insexpand_funcs(int copyID);
4748
callback_T *get_insert_callback(int type);
4849
void f_complete(typval_T *argvars, typval_T *rettv);
4950
void f_complete_add(typval_T *argvars, typval_T *rettv);

src/proto/ops.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@ void clear_oparg(oparg_T *oap);
1919
void cursor_pos_info(dict_T *dict);
2020
int set_operatorfunc_option(void);
2121
void free_operatorfunc_option(void);
22+
int set_ref_in_opfunc(int copyID);
2223
void do_pending_operator(cmdarg_T *cap, int old_col, int gui_yank);
2324
/* vim: set ft=c : */

0 commit comments

Comments
 (0)