summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <bram@vim.org>2013-04-15 12:27:36 +0200
committerBram Moolenaar <bram@vim.org>2013-04-15 12:27:36 +0200
commitab7669e4e96f960c41a5109dc26cac703ce1b907 (patch)
tree7d9a4131c7c22a3d21e4059063f21c3065abba14
parent13ad3a8c101789f63aff7ad93f6ac4ce3ad28e4d (diff)
downloadvim-ab7669e4e96f960c41a5109dc26cac703ce1b907.tar.gz
updated for version 7.3.893v7.3.893v7-3-893
Problem: Crash when using b:, w: or t: after closing the buffer, window or tabpage. Solution: Allocate the dictionary instead of having it part of the buffer/window/tabpage struct. (Yukihiro Nakadaira)
-rw-r--r--src/buffer.c22
-rw-r--r--src/eval.c45
-rw-r--r--src/fileio.c4
-rw-r--r--src/proto/eval.pro3
-rw-r--r--src/structs.h6
-rw-r--r--src/version.c2
-rw-r--r--src/window.c128
7 files changed, 129 insertions, 81 deletions
diff --git a/src/buffer.c b/src/buffer.c
index 2a9fe4d1..5ee62999 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -648,6 +648,9 @@ free_buffer(buf)
buf_T *buf;
{
free_buffer_stuff(buf, TRUE);
+#ifdef FEAT_EVAL
+ unref_var_dict(buf->b_vars);
+#endif
#ifdef FEAT_LUA
lua_buffer_free(buf);
#endif
@@ -689,8 +692,8 @@ free_buffer_stuff(buf, free_options)
#endif
}
#ifdef FEAT_EVAL
- vars_clear(&buf->b_vars.dv_hashtab); /* free all internal variables */
- hash_init(&buf->b_vars.dv_hashtab);
+ vars_clear(&buf->b_vars->dv_hashtab); /* free all internal variables */
+ hash_init(&buf->b_vars->dv_hashtab);
#endif
#ifdef FEAT_USR_CMDS
uc_clear(&buf->b_ucmds); /* clear local user commands */
@@ -1694,6 +1697,17 @@ buflist_new(ffname, sfname, lnum, flags)
vim_free(ffname);
return NULL;
}
+#ifdef FEAT_EVAL
+ /* init b: variables */
+ buf->b_vars = dict_alloc();
+ if (buf->b_vars == NULL)
+ {
+ vim_free(ffname);
+ vim_free(buf);
+ return NULL;
+ }
+ init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
+#endif
}
if (ffname != NULL)
@@ -1778,10 +1792,6 @@ buflist_new(ffname, sfname, lnum, flags)
buf->b_wininfo->wi_fpos.lnum = lnum;
buf->b_wininfo->wi_win = curwin;
-#ifdef FEAT_EVAL
- /* init b: variables */
- init_var_dict(&buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
-#endif
#ifdef FEAT_SYN_HL
hash_init(&buf->b_s.b_keywtab);
hash_init(&buf->b_s.b_keywtab_ic);
diff --git a/src/eval.c b/src/eval.c
index 49120b8c..5f9ddb4d 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2131,7 +2131,7 @@ list_buf_vars(first)
{
char_u numbuf[NUMBUFLEN];
- list_hashtable_vars(&curbuf->b_vars.dv_hashtab, (char_u *)"b:",
+ list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:",
TRUE, first);
sprintf((char *)numbuf, "%ld", (long)curbuf->b_changedtick);
@@ -2146,7 +2146,7 @@ list_buf_vars(first)
list_win_vars(first)
int *first;
{
- list_hashtable_vars(&curwin->w_vars.dv_hashtab,
+ list_hashtable_vars(&curwin->w_vars->dv_hashtab,
(char_u *)"w:", TRUE, first);
}
@@ -2158,7 +2158,7 @@ list_win_vars(first)
list_tab_vars(first)
int *first;
{
- list_hashtable_vars(&curtab->tp_vars.dv_hashtab,
+ list_hashtable_vars(&curtab->tp_vars->dv_hashtab,
(char_u *)"t:", TRUE, first);
}
#endif
@@ -3948,7 +3948,7 @@ get_user_var_name(xp, idx)
}
/* b: variables */
- ht = &curbuf->b_vars.dv_hashtab;
+ ht = &curbuf->b_vars->dv_hashtab;
if (bdone < ht->ht_used)
{
if (bdone++ == 0)
@@ -3966,7 +3966,7 @@ get_user_var_name(xp, idx)
}
/* w: variables */
- ht = &curwin->w_vars.dv_hashtab;
+ ht = &curwin->w_vars->dv_hashtab;
if (wdone < ht->ht_used)
{
if (wdone++ == 0)
@@ -3980,7 +3980,7 @@ get_user_var_name(xp, idx)
#ifdef FEAT_WINDOWS
/* t: variables */
- ht = &curtab->tp_vars.dv_hashtab;
+ ht = &curtab->tp_vars->dv_hashtab;
if (tdone < ht->ht_used)
{
if (tdone++ == 0)
@@ -6787,16 +6787,16 @@ garbage_collect()
/* buffer-local variables */
for (buf = firstbuf; buf != NULL; buf = buf->b_next)
- set_ref_in_ht(&buf->b_vars.dv_hashtab, copyID);
+ set_ref_in_item(&buf->b_bufvar.di_tv, copyID);
/* window-local variables */
FOR_ALL_TAB_WINDOWS(tp, wp)
- set_ref_in_ht(&wp->w_vars.dv_hashtab, copyID);
+ set_ref_in_item(&wp->w_winvar.di_tv, copyID);
#ifdef FEAT_WINDOWS
/* tabpage-local variables */
for (tp = first_tabpage; tp != NULL; tp = tp->tp_next)
- set_ref_in_ht(&tp->tp_vars.dv_hashtab, copyID);
+ set_ref_in_item(&tp->tp_winvar.di_tv, copyID);
#endif
/* global variables */
@@ -11156,7 +11156,7 @@ f_getbufvar(argvars, rettv)
* find_var_in_ht(). */
varname = (char_u *)"b:" + 2;
/* look up the variable */
- v = find_var_in_ht(&curbuf->b_vars.dv_hashtab, varname, FALSE);
+ v = find_var_in_ht(&curbuf->b_vars->dv_hashtab, varname, FALSE);
if (v != NULL)
copy_tv(&v->di_tv, rettv);
}
@@ -11779,7 +11779,7 @@ f_gettabvar(argvars, rettv)
if (tp != NULL && varname != NULL)
{
/* look up the variable */
- v = find_var_in_ht(&tp->tp_vars.dv_hashtab, varname, FALSE);
+ v = find_var_in_ht(&tp->tp_vars->dv_hashtab, varname, FALSE);
if (v != NULL)
copy_tv(&v->di_tv, rettv);
else if (argvars[2].v_type != VAR_UNKNOWN)
@@ -11935,7 +11935,7 @@ getwinvar(argvars, rettv, off)
* find_var_in_ht(). */
varname = (char_u *)"w:" + 2;
/* look up the variable */
- v = find_var_in_ht(&win->w_vars.dv_hashtab, varname, FALSE);
+ v = find_var_in_ht(&win->w_vars->dv_hashtab, varname, FALSE);
if (v != NULL)
copy_tv(&v->di_tv, rettv);
}
@@ -14333,7 +14333,7 @@ f_mode(argvars, rettv)
rettv->v_type = VAR_STRING;
}
-#ifdef FEAT_MZSCHEME
+#if defined(FEAT_MZSCHEME) || defined(PROTO)
/*
* "mzeval()" function
*/
@@ -20134,12 +20134,12 @@ find_var_ht(name, varname)
|| vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL)
return NULL;
if (*name == 'b') /* buffer variable */
- return &curbuf->b_vars.dv_hashtab;
+ return &curbuf->b_vars->dv_hashtab;
if (*name == 'w') /* window variable */
- return &curwin->w_vars.dv_hashtab;
+ return &curwin->w_vars->dv_hashtab;
#ifdef FEAT_WINDOWS
if (*name == 't') /* tab page variable */
- return &curtab->tp_vars.dv_hashtab;
+ return &curtab->tp_vars->dv_hashtab;
#endif
if (*name == 'v') /* v: variable */
return &vimvarht;
@@ -20229,6 +20229,19 @@ init_var_dict(dict, dict_var, scope)
}
/*
+ * Unreference a dictionary initialized by init_var_dict().
+ */
+ void
+unref_var_dict(dict)
+ dict_T *dict;
+{
+ /* Now the dict needs to be freed if no one else is using it, go back to
+ * normal reference counting. */
+ dict->dv_refcount -= DO_NOT_FREE_CNT - 1;
+ dict_unref(dict);
+}
+
+/*
* Clean up a list of internal variables.
* Frees all allocated variables and the value they contain.
* Clears hashtab "ht", does not free it.
diff --git a/src/fileio.c b/src/fileio.c
index 6e89b888..251d1554 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -8955,8 +8955,8 @@ win_found:
/* Hmm, original window disappeared. Just use the first one. */
curwin = firstwin;
# ifdef FEAT_EVAL
- vars_clear(&aucmd_win->w_vars.dv_hashtab); /* free all w: variables */
- hash_init(&aucmd_win->w_vars.dv_hashtab); /* re-use the hashtab */
+ vars_clear(&aucmd_win->w_vars->dv_hashtab); /* free all w: variables */
+ hash_init(&aucmd_win->w_vars->dv_hashtab); /* re-use the hashtab */
# endif
#else
curwin = aco->save_curwin;
diff --git a/src/proto/eval.pro b/src/proto/eval.pro
index 5ad27aa5..b23700d7 100644
--- a/src/proto/eval.pro
+++ b/src/proto/eval.pro
@@ -24,8 +24,8 @@ list_T *eval_spell_expr __ARGS((char_u *badword, char_u *expr));
int get_spellword __ARGS((list_T *list, char_u **pp));
typval_T *eval_expr __ARGS((char_u *arg, char_u **nextcmd));
int call_vim_function __ARGS((char_u *func, int argc, char_u **argv, int safe, int str_arg_only, typval_T *rettv));
-void *call_func_retstr __ARGS((char_u *func, int argc, char_u **argv, int safe));
long call_func_retnr __ARGS((char_u *func, int argc, char_u **argv, int safe));
+void *call_func_retstr __ARGS((char_u *func, int argc, char_u **argv, int safe));
void *call_func_retlist __ARGS((char_u *func, int argc, char_u **argv, int safe));
void *save_funccal __ARGS((void));
void restore_funccal __ARGS((void *vfc));
@@ -95,6 +95,7 @@ char_u *get_tv_string_chk __ARGS((typval_T *varp));
char_u *get_var_value __ARGS((char_u *name));
void new_script_vars __ARGS((scid_T id));
void init_var_dict __ARGS((dict_T *dict, dictitem_T *dict_var, int scope));
+void unref_var_dict __ARGS((dict_T *dict));
void vars_clear __ARGS((hashtab_T *ht));
void copy_tv __ARGS((typval_T *from, typval_T *to));
void ex_echo __ARGS((exarg_T *eap));
diff --git a/src/structs.h b/src/structs.h
index 36440c3c..63051295 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1611,7 +1611,7 @@ struct file_buffer
#ifdef FEAT_EVAL
dictitem_T b_bufvar; /* variable for "b:" Dictionary */
- dict_T b_vars; /* internal variables, local to buffer */
+ dict_T *b_vars; /* internal variables, local to buffer */
#endif
#if defined(FEAT_BEVAL) && defined(FEAT_EVAL)
@@ -1757,7 +1757,7 @@ struct tabpage_S
frame_T *(tp_snapshot[SNAP_COUNT]); /* window layout snapshots */
#ifdef FEAT_EVAL
dictitem_T tp_winvar; /* variable for "t:" Dictionary */
- dict_T tp_vars; /* internal variables, local to tab page */
+ dict_T *tp_vars; /* internal variables, local to tab page */
#endif
};
@@ -2080,7 +2080,7 @@ struct window_S
#ifdef FEAT_EVAL
dictitem_T w_winvar; /* variable for "w:" Dictionary */
- dict_T w_vars; /* internal variables, local to window */
+ dict_T *w_vars; /* internal variables, local to window */
#endif
#if defined(FEAT_RIGHTLEFT) && defined(FEAT_FKMAP)
diff --git a/src/version.c b/src/version.c
index 8683cec4..309114b3 100644
--- a/src/version.c
+++ b/src/version.c
@@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 893,
+/**/
892,
/**/
891,
diff --git a/src/window.c b/src/window.c
index 1a09c914..fadbb925 100644
--- a/src/window.c
+++ b/src/window.c
@@ -3457,25 +3457,35 @@ win_init_size()
alloc_tabpage()
{
tabpage_T *tp;
+# ifdef FEAT_GUI
+ int i;
+# endif
+
tp = (tabpage_T *)alloc_clear((unsigned)sizeof(tabpage_T));
- if (tp != NULL)
+ if (tp == NULL)
+ return NULL;
+
+# ifdef FEAT_EVAL
+ /* init t: variables */
+ tp->tp_vars = dict_alloc();
+ if (tp->tp_vars == NULL)
{
-# ifdef FEAT_GUI
- int i;
+ vim_free(tp);
+ return NULL;
+ }
+ init_var_dict(tp->tp_vars, &tp->tp_winvar, VAR_SCOPE);
+# endif
- for (i = 0; i < 3; i++)
- tp->tp_prev_which_scrollbars[i] = -1;
+# ifdef FEAT_GUI
+ for (i = 0; i < 3; i++)
+ tp->tp_prev_which_scrollbars[i] = -1;
# endif
# ifdef FEAT_DIFF
- tp->tp_diff_invalid = TRUE;
+ tp->tp_diff_invalid = TRUE;
# endif
-#ifdef FEAT_EVAL
- /* init t: variables */
- init_var_dict(&tp->tp_vars, &tp->tp_winvar, VAR_SCOPE);
-#endif
- tp->tp_ch_used = p_ch;
- }
+ tp->tp_ch_used = p_ch;
+
return tp;
}
@@ -3491,7 +3501,9 @@ free_tabpage(tp)
for (idx = 0; idx < SNAP_COUNT; ++idx)
clear_snapshot(tp, idx);
#ifdef FEAT_EVAL
- vars_clear(&tp->tp_vars.dv_hashtab); /* free all t: variables */
+ vars_clear(&tp->tp_vars->dv_hashtab); /* free all t: variables */
+ hash_init(&tp->tp_vars->dv_hashtab);
+ unref_var_dict(tp->tp_vars);
#endif
vim_free(tp);
}
@@ -4363,71 +4375,79 @@ win_alloc(after, hidden)
* allocate window structure and linesizes arrays
*/
new_wp = (win_T *)alloc_clear((unsigned)sizeof(win_T));
- if (new_wp != NULL && win_alloc_lines(new_wp) == FAIL)
+ if (new_wp == NULL)
+ return NULL;
+
+ if (win_alloc_lines(new_wp) == FAIL)
{
vim_free(new_wp);
- new_wp = NULL;
+ return NULL;
}
- if (new_wp != NULL)
+#ifdef FEAT_EVAL
+ /* init w: variables */
+ new_wp->w_vars = dict_alloc();
+ if (new_wp->w_vars == NULL)
{
+ win_free_lsize(new_wp);
+ vim_free(new_wp);
+ return NULL;
+ }
+ init_var_dict(new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
+#endif
+
#ifdef FEAT_AUTOCMD
- /* Don't execute autocommands while the window is not properly
- * initialized yet. gui_create_scrollbar() may trigger a FocusGained
- * event. */
- block_autocmds();
+ /* Don't execute autocommands while the window is not properly
+ * initialized yet. gui_create_scrollbar() may trigger a FocusGained
+ * event. */
+ block_autocmds();
#endif
- /*
- * link the window in the window list
- */
+ /*
+ * link the window in the window list
+ */
#ifdef FEAT_WINDOWS
- if (!hidden)
- win_append(after, new_wp);
+ if (!hidden)
+ win_append(after, new_wp);
#endif
#ifdef FEAT_VERTSPLIT
- new_wp->w_wincol = 0;
- new_wp->w_width = Columns;
+ new_wp->w_wincol = 0;
+ new_wp->w_width = Columns;
#endif
- /* position the display and the cursor at the top of the file. */
- new_wp->w_topline = 1;
+ /* position the display and the cursor at the top of the file. */
+ new_wp->w_topline = 1;
#ifdef FEAT_DIFF
- new_wp->w_topfill = 0;
+ new_wp->w_topfill = 0;
#endif
- new_wp->w_botline = 2;
- new_wp->w_cursor.lnum = 1;
+ new_wp->w_botline = 2;
+ new_wp->w_cursor.lnum = 1;
#ifdef FEAT_SCROLLBIND
- new_wp->w_scbind_pos = 1;
+ new_wp->w_scbind_pos = 1;
#endif
- /* We won't calculate w_fraction until resizing the window */
- new_wp->w_fraction = 0;
- new_wp->w_prev_fraction_row = -1;
+ /* We won't calculate w_fraction until resizing the window */
+ new_wp->w_fraction = 0;
+ new_wp->w_prev_fraction_row = -1;
#ifdef FEAT_GUI
- if (gui.in_use)
- {
- gui_create_scrollbar(&new_wp->w_scrollbars[SBAR_LEFT],
- SBAR_LEFT, new_wp);
- gui_create_scrollbar(&new_wp->w_scrollbars[SBAR_RIGHT],
- SBAR_RIGHT, new_wp);
- }
-#endif
-#ifdef FEAT_EVAL
- /* init w: variables */
- init_var_dict(&new_wp->w_vars, &new_wp->w_winvar, VAR_SCOPE);
+ if (gui.in_use)
+ {
+ gui_create_scrollbar(&new_wp->w_scrollbars[SBAR_LEFT],
+ SBAR_LEFT, new_wp);
+ gui_create_scrollbar(&new_wp->w_scrollbars[SBAR_RIGHT],
+ SBAR_RIGHT, new_wp);
+ }
#endif
#ifdef FEAT_FOLDING
- foldInitWin(new_wp);
+ foldInitWin(new_wp);
#endif
#ifdef FEAT_AUTOCMD
- unblock_autocmds();
+ unblock_autocmds();
#endif
#ifdef FEAT_SEARCH_EXTRA
- new_wp->w_match_head = NULL;
- new_wp->w_next_match_id = 4;
+ new_wp->w_match_head = NULL;
+ new_wp->w_next_match_id = 4;
#endif
- }
return new_wp;
}
@@ -4488,7 +4508,9 @@ win_free(wp, tp)
clear_winopt(&wp->w_allbuf_opt);
#ifdef FEAT_EVAL
- vars_clear(&wp->w_vars.dv_hashtab); /* free all w: variables */
+ vars_clear(&wp->w_vars->dv_hashtab); /* free all w: variables */
+ hash_init(&wp->w_vars->dv_hashtab);
+ unref_var_dict(wp->w_vars);
#endif
if (prevwin == wp)