patch 8.0.0365: might free a dict item that wasn't allocated

Problem:    Might free a dict item that wasn't allocated.
Solution:   Call dictitem_free(). (Nikolai Pavlov)  Use this for
            b:changedtick.
This commit is contained in:
Bram Moolenaar
2017-02-25 14:59:34 +01:00
parent d3f78dc9eb
commit 95c526e1f6
12 changed files with 40 additions and 50 deletions

View File

@@ -832,7 +832,6 @@ free_buffer(buf_T *buf)
free_buffer_stuff(buf, TRUE); free_buffer_stuff(buf, TRUE);
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
unref_var_dict(buf->b_vars); unref_var_dict(buf->b_vars);
buf->b_changedtick = &buf->b_ct_val;
#endif #endif
#ifdef FEAT_LUA #ifdef FEAT_LUA
lua_buffer_free(buf); lua_buffer_free(buf);
@@ -874,31 +873,20 @@ free_buffer(buf_T *buf)
} }
/* /*
* Initializes buf->b_changedtick. * Initializes b:changedtick.
*/ */
static void static void
init_changedtick(buf_T *buf) init_changedtick(buf_T *buf)
{ {
#ifdef FEAT_EVAL dictitem_T *di = (dictitem_T *)&buf->b_ct_di;
dictitem_T *di = dictitem_alloc((char_u *)"changedtick");
if (di != NULL) di->di_flags = DI_FLAGS_FIX | DI_FLAGS_RO;
{
di->di_flags |= DI_FLAGS_FIX | DI_FLAGS_RO;
di->di_tv.v_type = VAR_NUMBER; di->di_tv.v_type = VAR_NUMBER;
di->di_tv.v_lock = VAR_FIXED; di->di_tv.v_lock = VAR_FIXED;
di->di_tv.vval.v_number = 0; di->di_tv.vval.v_number = 0;
if (dict_add(buf->b_vars, di) == OK)
buf->b_changedtick = &di->di_tv.vval.v_number; STRCPY(buf->b_ct_di.di_key, "changedtick");
else (void)dict_add(buf->b_vars, di);
{
vim_free(di);
buf->b_changedtick = &buf->b_ct_val;
}
}
else
#endif
buf->b_changedtick = &buf->b_ct_val;
} }
/* /*
@@ -919,12 +907,12 @@ free_buffer_stuff(
} }
#ifdef FEAT_EVAL #ifdef FEAT_EVAL
{ {
varnumber_T tick = *buf->b_changedtick; varnumber_T tick = CHANGEDTICK(buf);
vars_clear(&buf->b_vars->dv_hashtab); /* free all buffer variables */ vars_clear(&buf->b_vars->dv_hashtab); /* free all buffer variables */
hash_init(&buf->b_vars->dv_hashtab); hash_init(&buf->b_vars->dv_hashtab);
init_changedtick(buf); init_changedtick(buf);
*buf->b_changedtick = tick; CHANGEDTICK(buf) = tick;
} }
#endif #endif
#ifdef FEAT_USR_CMDS #ifdef FEAT_USR_CMDS

View File

@@ -88,8 +88,7 @@ dict_free_contents(dict_T *d)
* something recursive causing trouble. */ * something recursive causing trouble. */
di = HI2DI(hi); di = HI2DI(hi);
hash_remove(&d->dv_hashtab, hi); hash_remove(&d->dv_hashtab, hi);
clear_tv(&di->di_tv); dictitem_free(di);
vim_free(di);
--todo; --todo;
} }
} }

View File

@@ -1668,7 +1668,7 @@ ins_redraw(
#ifdef FEAT_AUTOCMD #ifdef FEAT_AUTOCMD
/* Trigger TextChangedI if b_changedtick differs. */ /* Trigger TextChangedI if b_changedtick differs. */
if (ready && has_textchangedI() if (ready && has_textchangedI()
&& last_changedtick != *curbuf->b_changedtick && last_changedtick != CHANGEDTICK(curbuf)
# ifdef FEAT_INS_EXPAND # ifdef FEAT_INS_EXPAND
&& !pum_visible() && !pum_visible()
# endif # endif
@@ -1677,7 +1677,7 @@ ins_redraw(
if (last_changedtick_buf == curbuf) if (last_changedtick_buf == curbuf)
apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf);
last_changedtick_buf = curbuf; last_changedtick_buf = curbuf;
last_changedtick = *curbuf->b_changedtick; last_changedtick = CHANGEDTICK(curbuf);
} }
#endif #endif

View File

@@ -2550,7 +2550,7 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
if (lnum < 0) /* ignore type error in {lnum} arg */ if (lnum < 0) /* ignore type error in {lnum} arg */
lnum = 0; lnum = 0;
if (lnum != prev_lnum if (lnum != prev_lnum
|| changedtick != *curbuf->b_changedtick || changedtick != CHANGEDTICK(curbuf)
|| fnum != curbuf->b_fnum) || fnum != curbuf->b_fnum)
{ {
/* New line, buffer, change: need to get the values. */ /* New line, buffer, change: need to get the values. */
@@ -2572,7 +2572,7 @@ f_diff_hlID(typval_T *argvars UNUSED, typval_T *rettv UNUSED)
else else
hlID = (hlf_T)0; hlID = (hlf_T)0;
prev_lnum = lnum; prev_lnum = lnum;
changedtick = *curbuf->b_changedtick; changedtick = CHANGEDTICK(curbuf);
fnum = curbuf->b_fnum; fnum = curbuf->b_fnum;
} }
@@ -3957,7 +3957,7 @@ get_buffer_info(buf_T *buf)
dict_add_nr_str(dict, "loaded", buf->b_ml.ml_mfp != NULL, NULL); dict_add_nr_str(dict, "loaded", buf->b_ml.ml_mfp != NULL, NULL);
dict_add_nr_str(dict, "listed", buf->b_p_bl, NULL); dict_add_nr_str(dict, "listed", buf->b_p_bl, NULL);
dict_add_nr_str(dict, "changed", bufIsChanged(buf), NULL); dict_add_nr_str(dict, "changed", bufIsChanged(buf), NULL);
dict_add_nr_str(dict, "changedtick", *buf->b_changedtick, NULL); dict_add_nr_str(dict, "changedtick", CHANGEDTICK(buf), NULL);
dict_add_nr_str(dict, "hidden", dict_add_nr_str(dict, "hidden",
buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0, buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0,
NULL); NULL);

View File

@@ -660,7 +660,7 @@ do_exmode(
need_wait_return = FALSE; need_wait_return = FALSE;
ex_pressedreturn = FALSE; ex_pressedreturn = FALSE;
ex_no_reprint = FALSE; ex_no_reprint = FALSE;
changedtick = *curbuf->b_changedtick; changedtick = CHANGEDTICK(curbuf);
prev_msg_row = msg_row; prev_msg_row = msg_row;
prev_line = curwin->w_cursor.lnum; prev_line = curwin->w_cursor.lnum;
if (improved) if (improved)
@@ -673,7 +673,7 @@ do_exmode(
lines_left = Rows - 1; lines_left = Rows - 1;
if ((prev_line != curwin->w_cursor.lnum if ((prev_line != curwin->w_cursor.lnum
|| changedtick != *curbuf->b_changedtick) && !ex_no_reprint) || changedtick != CHANGEDTICK(curbuf)) && !ex_no_reprint)
{ {
if (curbuf->b_ml.ml_flags & ML_EMPTY) if (curbuf->b_ml.ml_flags & ML_EMPTY)
EMSG(_(e_emptybuf)); EMSG(_(e_emptybuf));

View File

@@ -4924,11 +4924,11 @@ restore_backup:
{ {
unchanged(buf, TRUE); unchanged(buf, TRUE);
#ifdef FEAT_AUTOCMD #ifdef FEAT_AUTOCMD
/* buf->b_changedtick is always incremented in unchanged() but that /* b:changedtick is always incremented in unchanged() but that
* should not trigger a TextChanged event. */ * should not trigger a TextChanged event. */
if (last_changedtick + 1 == *buf->b_changedtick if (last_changedtick + 1 == CHANGEDTICK(buf)
&& last_changedtick_buf == buf) && last_changedtick_buf == buf)
last_changedtick = *buf->b_changedtick; last_changedtick = CHANGEDTICK(buf);
#endif #endif
u_unchanged(buf); u_unchanged(buf);
u_update_save_nr(buf); u_update_save_nr(buf);

View File

@@ -1162,15 +1162,15 @@ main_loop(
#endif #endif
#ifdef FEAT_AUTOCMD #ifdef FEAT_AUTOCMD
/* Trigger TextChanged if b_changedtick differs. */ /* Trigger TextChanged if b:changedtick differs. */
if (!finish_op && has_textchanged() if (!finish_op && has_textchanged()
&& last_changedtick != *curbuf->b_changedtick) && last_changedtick != CHANGEDTICK(curbuf))
{ {
if (last_changedtick_buf == curbuf) if (last_changedtick_buf == curbuf)
apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL,
FALSE, curbuf); FALSE, curbuf);
last_changedtick_buf = curbuf; last_changedtick_buf = curbuf;
last_changedtick = *curbuf->b_changedtick; last_changedtick = CHANGEDTICK(curbuf);
} }
#endif #endif
@@ -1388,11 +1388,11 @@ getout(int exitval)
/* Autocmd must have close the buffer already, skip. */ /* Autocmd must have close the buffer already, skip. */
continue; continue;
buf = wp->w_buffer; buf = wp->w_buffer;
if (buf->b_ct_val != -1) if (CHANGEDTICK(buf) != -1)
{ {
apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname,
buf->b_fname, FALSE, buf); buf->b_fname, FALSE, buf);
buf->b_ct_val = -1; /* note that we did it already */ CHANGEDTICK(buf) = -1; /* note that we did it already */
/* start all over, autocommands may mess up the lists */ /* start all over, autocommands may mess up the lists */
next_tp = first_tabpage; next_tp = first_tabpage;
break; break;

View File

@@ -1649,7 +1649,7 @@ ml_recover(void)
if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL)) if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL))
{ {
changed_int(); changed_int();
++*curbuf->b_changedtick; ++CHANGEDTICK(curbuf);
} }
} }
else else
@@ -1663,7 +1663,7 @@ ml_recover(void)
if (i != 0) if (i != 0)
{ {
changed_int(); changed_int();
++*curbuf->b_changedtick; ++CHANGEDTICK(curbuf);
break; break;
} }
} }

View File

@@ -502,11 +502,11 @@ get_breakindent_win(
/* used cached indent, unless pointer or 'tabstop' changed */ /* used cached indent, unless pointer or 'tabstop' changed */
if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts
|| prev_tick != *wp->w_buffer->b_changedtick) || prev_tick != CHANGEDTICK(wp->w_buffer))
{ {
prev_line = line; prev_line = line;
prev_ts = wp->w_buffer->b_p_ts; prev_ts = wp->w_buffer->b_p_ts;
prev_tick = *wp->w_buffer->b_changedtick; prev_tick = CHANGEDTICK(wp->w_buffer);
prev_indent = get_indent_str(line, prev_indent = get_indent_str(line,
(int)wp->w_buffer->b_p_ts, wp->w_p_list); (int)wp->w_buffer->b_p_ts, wp->w_p_list);
} }
@@ -2768,7 +2768,7 @@ changed(void)
} }
changed_int(); changed_int();
} }
++*curbuf->b_changedtick; ++CHANGEDTICK(curbuf);
} }
/* /*
@@ -3195,7 +3195,7 @@ unchanged(
need_maketitle = TRUE; /* set window title later */ need_maketitle = TRUE; /* set window title later */
#endif #endif
} }
++*buf->b_changedtick; ++CHANGEDTICK(buf);
#ifdef FEAT_NETBEANS_INTG #ifdef FEAT_NETBEANS_INTG
netbeans_unmodified(buf); netbeans_unmodified(buf);
#endif #endif

View File

@@ -1916,9 +1916,10 @@ struct file_buffer
int b_changed; /* 'modified': Set to TRUE if something in the int b_changed; /* 'modified': Set to TRUE if something in the
file has been changed and not written out. */ file has been changed and not written out. */
varnumber_T *b_changedtick; /* points into b:changedtick or b_ct_val; dictitem16_T b_ct_di; /* holds the b:changedtick value in
b_ct_di.di_tv.vval.v_number;
incremented for each change, also for undo */ incremented for each change, also for undo */
varnumber_T b_ct_val; /* fallback for b:changedtick */ #define CHANGEDTICK(buf) ((buf)->b_ct_di.di_tv.vval.v_number)
int b_saving; /* Set to TRUE if we are in the middle of int b_saving; /* Set to TRUE if we are in the middle of
saving the buffer. */ saving the buffer. */

View File

@@ -516,13 +516,13 @@ syntax_start(win_T *wp, linenr_T lnum)
*/ */
if (syn_block != wp->w_s if (syn_block != wp->w_s
|| syn_buf != wp->w_buffer || syn_buf != wp->w_buffer
|| changedtick != *syn_buf->b_changedtick) || changedtick != CHANGEDTICK(syn_buf))
{ {
invalidate_current_state(); invalidate_current_state();
syn_buf = wp->w_buffer; syn_buf = wp->w_buffer;
syn_block = wp->w_s; syn_block = wp->w_s;
} }
changedtick = *syn_buf->b_changedtick; changedtick = CHANGEDTICK(syn_buf);
syn_win = wp; syn_win = wp;
/* /*

View File

@@ -764,6 +764,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
365,
/**/ /**/
364, 364,
/**/ /**/