Problem: Exe stack length can be wrong without being detected.
Solution: Add a check when ABORT_ON_INTERNAL_ERROR is defined.
int did_save_redobuff = FALSE;
save_redo_T save_redo;
int save_KeyTyped = KeyTyped;
+ ESTACK_CHECK_DECLARATION
/*
* Quickly return if there are no autocommands for this event or
// name and lnum are filled in later
estack_push(ETYPE_AUCMD, NULL, 0);
+ ESTACK_CHECK_SETUP
#ifdef FEAT_EVAL
save_current_sctx = current_sctx;
filechangeshell_busy = FALSE;
autocmd_nested = save_autocmd_nested;
vim_free(SOURCING_NAME);
+ ESTACK_CHECK_NOW
estack_pop();
vim_free(autocmd_fname);
autocmd_fname = save_autocmd_fname;
#ifdef FEAT_EVAL
sctx_T save_current_sctx;
#endif
+ ESTACK_CHECK_DECLARATION
prev = -1;
for (s = ml_get(lnum); *s != NUL; ++s)
// prepare for emsg()
estack_push(ETYPE_MODELINE, (char_u *)"modelines", lnum);
+ ESTACK_CHECK_SETUP
end = FALSE;
while (end == FALSE)
s = e + 1; // advance to next part
}
+ ESTACK_CHECK_NOW
estack_pop();
vim_free(linecopy);
}
# define cmd_cookie cookie
#endif
static int call_depth = 0; // recursiveness
+ ESTACK_CHECK_DECLARATION
#ifdef FEAT_EVAL
// For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory
estack_push(ETYPE_EXCEPT, current_exception->throw_name,
current_exception->throw_lnum);
+ ESTACK_CHECK_SETUP
current_exception->throw_name = NULL;
discard_current_exception(); // uses IObuff if 'verbose'
vim_free(p);
}
vim_free(SOURCING_NAME);
+ ESTACK_CHECK_NOW
estack_pop();
}
#else
# define ERROR_IF_POPUP_WINDOW 0
#endif
+
+
+#ifdef ABORT_ON_INTERNAL_ERROR
+# define ESTACK_CHECK_DECLARATION int estack_len_before;
+# define ESTACK_CHECK_SETUP estack_len_before = exestack.ga_len;
+# define ESTACK_CHECK_NOW if (estack_len_before != exestack.ga_len) \
+ siemsg("Exestack length expected: %d, actual: %d", estack_len_before, exestack.ga_len);
+#else
+# define ESTACK_CHECK_DECLARATION
+# define ESTACK_CHECK_SETUP
+# define ESTACK_CHECK_NOW
+#endif
char_u **cmds = parmp->pre_commands;
int cnt = parmp->n_pre_commands;
int i;
+ ESTACK_CHECK_DECLARATION
if (cnt > 0)
{
curwin->w_cursor.lnum = 0; // just in case..
estack_push(ETYPE_ARGS, (char_u *)_("pre-vimrc command line"), 0);
+ ESTACK_CHECK_SETUP
# ifdef FEAT_EVAL
current_sctx.sc_sid = SID_CMDARG;
# endif
for (i = 0; i < cnt; ++i)
do_cmdline_cmd(cmds[i]);
+ ESTACK_CHECK_NOW
estack_pop();
# ifdef FEAT_EVAL
current_sctx.sc_sid = 0;
exe_commands(mparm_T *parmp)
{
int i;
+ ESTACK_CHECK_DECLARATION
/*
* We start commands on line 0, make "vim +/pat file" match a
if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1)
curwin->w_cursor.lnum = 0;
estack_push(ETYPE_ARGS, (char_u *)"command line", 0);
+ ESTACK_CHECK_SETUP
#ifdef FEAT_EVAL
current_sctx.sc_sid = SID_CARG;
current_sctx.sc_seq = 0;
if (parmp->cmds_tofree[i])
vim_free(parmp->commands[i]);
}
+ ESTACK_CHECK_NOW
estack_pop();
#ifdef FEAT_EVAL
current_sctx.sc_sid = 0;
#ifdef FEAT_EVAL
sctx_T save_current_sctx;
#endif
+ ESTACK_CHECK_DECLARATION
if ((initstr = mch_getenv(env)) != NULL && *initstr != NUL)
{
if (is_viminit)
vimrc_found(NULL, NULL);
estack_push(ETYPE_ENV, env, 0);
+ ESTACK_CHECK_SETUP
#ifdef FEAT_EVAL
save_current_sctx = current_sctx;
current_sctx.sc_sid = SID_ENV;
#endif
do_cmdline_cmd(initstr);
+ ESTACK_CHECK_NOW
estack_pop();
#ifdef FEAT_EVAL
current_sctx = save_current_sctx;
int abbr;
int hash;
buf_T *bp;
+ ESTACK_CHECK_DECLARATION
validate_maphash();
// avoids giving error messages
estack_push(ETYPE_INTERNAL, (char_u *)"mappings", 0);
+ ESTACK_CHECK_SETUP
// Do this once for each buffer, and then once for global
// mappings/abbreviations with bp == NULL
if (bp == NULL)
break;
}
+ ESTACK_CHECK_NOW
estack_pop();
}
proftime_T wait_start;
#endif
int trigger_source_post = FALSE;
+ ESTACK_CHECK_DECLARATION
p = expand_env_save(fname);
if (p == NULL)
// Keep the sourcing name/lnum, for recursive calls.
estack_push(ETYPE_SCRIPT, fname_exp, 0);
+ ESTACK_CHECK_SETUP
#ifdef STARTUPTIME
if (time_fd != NULL)
if (got_int)
emsg(_(e_interr));
+ ESTACK_CHECK_NOW
estack_pop();
if (p_verbose > 1)
{
int c = 0;
int res;
int did_estack_push = FALSE;
+ ESTACK_CHECK_DECLARATION
fd = mch_fopen((char *)fname, "r");
if (fd == NULL)
// Set sourcing_name, so that error messages mention the file name.
estack_push(ETYPE_SPELL, fname, 0);
+ ESTACK_CHECK_SETUP
did_estack_push = TRUE;
/*
if (fd != NULL)
fclose(fd);
if (did_estack_push)
+ {
+ ESTACK_CHECK_NOW
estack_pop();
+ }
return lp;
}
proftime_T call_start;
int started_profiling = FALSE;
#endif
+ ESTACK_CHECK_DECLARATION
// If depth of calling is getting too high, don't execute the function
if (depth >= p_mfd)
}
estack_push_ufunc(ETYPE_UFUNC, fp, 1);
+ ESTACK_CHECK_SETUP
if (p_verbose >= 12)
{
++no_wait_return;
--no_wait_return;
}
+ ESTACK_CHECK_NOW
estack_pop();
current_sctx = save_current_sctx;
#ifdef FEAT_PROFILE
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 98,
/**/
97,
/**/