# HG changeset patch # User Christian Brabandt # Date 1488031205 -3600 # Node ID 835604f3c37aea177343a9af8d30240bc3d8a68a # Parent 32704a1de17c74d48a2e8276a4f0e4758fca4aa9 patch 8.0.0365: might free a dict item that wasn't allocated commit https://github.com/vim/vim/commit/95c526e1f6d76acafee4b21f5701d6d6ac8c4b5f Author: Bram Moolenaar Date: Sat Feb 25 14:59:34 2017 +0100 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. diff --git a/src/buffer.c b/src/buffer.c --- a/src/buffer.c +++ b/src/buffer.c @@ -832,7 +832,6 @@ free_buffer(buf_T *buf) free_buffer_stuff(buf, TRUE); #ifdef FEAT_EVAL unref_var_dict(buf->b_vars); - buf->b_changedtick = &buf->b_ct_val; #endif #ifdef FEAT_LUA lua_buffer_free(buf); @@ -874,31 +873,20 @@ free_buffer(buf_T *buf) } /* - * Initializes buf->b_changedtick. + * Initializes b:changedtick. */ static void init_changedtick(buf_T *buf) { -#ifdef FEAT_EVAL - dictitem_T *di = dictitem_alloc((char_u *)"changedtick"); - - if (di != NULL) - { - di->di_flags |= DI_FLAGS_FIX | DI_FLAGS_RO; - di->di_tv.v_type = VAR_NUMBER; - di->di_tv.v_lock = VAR_FIXED; - di->di_tv.vval.v_number = 0; - if (dict_add(buf->b_vars, di) == OK) - buf->b_changedtick = &di->di_tv.vval.v_number; - else - { - vim_free(di); - buf->b_changedtick = &buf->b_ct_val; - } - } - else -#endif - buf->b_changedtick = &buf->b_ct_val; + dictitem_T *di = (dictitem_T *)&buf->b_ct_di; + + di->di_flags = DI_FLAGS_FIX | DI_FLAGS_RO; + di->di_tv.v_type = VAR_NUMBER; + di->di_tv.v_lock = VAR_FIXED; + di->di_tv.vval.v_number = 0; + + STRCPY(buf->b_ct_di.di_key, "changedtick"); + (void)dict_add(buf->b_vars, di); } /* @@ -919,12 +907,12 @@ free_buffer_stuff( } #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 */ hash_init(&buf->b_vars->dv_hashtab); init_changedtick(buf); - *buf->b_changedtick = tick; + CHANGEDTICK(buf) = tick; } #endif #ifdef FEAT_USR_CMDS diff --git a/src/dict.c b/src/dict.c --- a/src/dict.c +++ b/src/dict.c @@ -88,8 +88,7 @@ dict_free_contents(dict_T *d) * something recursive causing trouble. */ di = HI2DI(hi); hash_remove(&d->dv_hashtab, hi); - clear_tv(&di->di_tv); - vim_free(di); + dictitem_free(di); --todo; } } diff --git a/src/edit.c b/src/edit.c --- a/src/edit.c +++ b/src/edit.c @@ -1668,7 +1668,7 @@ ins_redraw( #ifdef FEAT_AUTOCMD /* Trigger TextChangedI if b_changedtick differs. */ if (ready && has_textchangedI() - && last_changedtick != *curbuf->b_changedtick + && last_changedtick != CHANGEDTICK(curbuf) # ifdef FEAT_INS_EXPAND && !pum_visible() # endif @@ -1677,7 +1677,7 @@ ins_redraw( if (last_changedtick_buf == curbuf) apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); last_changedtick_buf = curbuf; - last_changedtick = *curbuf->b_changedtick; + last_changedtick = CHANGEDTICK(curbuf); } #endif diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2550,7 +2550,7 @@ f_diff_hlID(typval_T *argvars UNUSED, ty if (lnum < 0) /* ignore type error in {lnum} arg */ lnum = 0; if (lnum != prev_lnum - || changedtick != *curbuf->b_changedtick + || changedtick != CHANGEDTICK(curbuf) || fnum != curbuf->b_fnum) { /* New line, buffer, change: need to get the values. */ @@ -2572,7 +2572,7 @@ f_diff_hlID(typval_T *argvars UNUSED, ty else hlID = (hlf_T)0; prev_lnum = lnum; - changedtick = *curbuf->b_changedtick; + changedtick = CHANGEDTICK(curbuf); 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, "listed", buf->b_p_bl, 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", buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0, NULL); diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -660,7 +660,7 @@ do_exmode( need_wait_return = FALSE; ex_pressedreturn = FALSE; ex_no_reprint = FALSE; - changedtick = *curbuf->b_changedtick; + changedtick = CHANGEDTICK(curbuf); prev_msg_row = msg_row; prev_line = curwin->w_cursor.lnum; if (improved) @@ -673,7 +673,7 @@ do_exmode( lines_left = Rows - 1; 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) EMSG(_(e_emptybuf)); diff --git a/src/fileio.c b/src/fileio.c --- a/src/fileio.c +++ b/src/fileio.c @@ -4924,11 +4924,11 @@ restore_backup: { unchanged(buf, TRUE); #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. */ - if (last_changedtick + 1 == *buf->b_changedtick + if (last_changedtick + 1 == CHANGEDTICK(buf) && last_changedtick_buf == buf) - last_changedtick = *buf->b_changedtick; + last_changedtick = CHANGEDTICK(buf); #endif u_unchanged(buf); u_update_save_nr(buf); diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -1162,15 +1162,15 @@ main_loop( #endif #ifdef FEAT_AUTOCMD - /* Trigger TextChanged if b_changedtick differs. */ + /* Trigger TextChanged if b:changedtick differs. */ if (!finish_op && has_textchanged() - && last_changedtick != *curbuf->b_changedtick) + && last_changedtick != CHANGEDTICK(curbuf)) { if (last_changedtick_buf == curbuf) apply_autocmds(EVENT_TEXTCHANGED, NULL, NULL, FALSE, curbuf); last_changedtick_buf = curbuf; - last_changedtick = *curbuf->b_changedtick; + last_changedtick = CHANGEDTICK(curbuf); } #endif @@ -1388,11 +1388,11 @@ getout(int exitval) /* Autocmd must have close the buffer already, skip. */ continue; buf = wp->w_buffer; - if (buf->b_ct_val != -1) + if (CHANGEDTICK(buf) != -1) { apply_autocmds(EVENT_BUFWINLEAVE, buf->b_fname, 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 */ next_tp = first_tabpage; break; diff --git a/src/memline.c b/src/memline.c --- a/src/memline.c +++ b/src/memline.c @@ -1649,7 +1649,7 @@ ml_recover(void) if (!(curbuf->b_ml.ml_line_count == 2 && *ml_get(1) == NUL)) { changed_int(); - ++*curbuf->b_changedtick; + ++CHANGEDTICK(curbuf); } } else @@ -1663,7 +1663,7 @@ ml_recover(void) if (i != 0) { changed_int(); - ++*curbuf->b_changedtick; + ++CHANGEDTICK(curbuf); break; } } diff --git a/src/misc1.c b/src/misc1.c --- a/src/misc1.c +++ b/src/misc1.c @@ -502,11 +502,11 @@ get_breakindent_win( /* used cached indent, unless pointer or 'tabstop' changed */ 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_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, (int)wp->w_buffer->b_p_ts, wp->w_p_list); } @@ -2768,7 +2768,7 @@ changed(void) } changed_int(); } - ++*curbuf->b_changedtick; + ++CHANGEDTICK(curbuf); } /* @@ -3195,7 +3195,7 @@ unchanged( need_maketitle = TRUE; /* set window title later */ #endif } - ++*buf->b_changedtick; + ++CHANGEDTICK(buf); #ifdef FEAT_NETBEANS_INTG netbeans_unmodified(buf); #endif diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1916,9 +1916,10 @@ struct file_buffer int b_changed; /* 'modified': Set to TRUE if something in the 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 */ - 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 saving the buffer. */ diff --git a/src/syntax.c b/src/syntax.c --- a/src/syntax.c +++ b/src/syntax.c @@ -516,13 +516,13 @@ syntax_start(win_T *wp, linenr_T lnum) */ if (syn_block != wp->w_s || syn_buf != wp->w_buffer - || changedtick != *syn_buf->b_changedtick) + || changedtick != CHANGEDTICK(syn_buf)) { invalidate_current_state(); syn_buf = wp->w_buffer; syn_block = wp->w_s; } - changedtick = *syn_buf->b_changedtick; + changedtick = CHANGEDTICK(syn_buf); syn_win = wp; /* diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -765,6 +765,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 365, +/**/ 364, /**/ 363,