# HG changeset patch # User Bram Moolenaar # Date 1578427207 -3600 # Node ID af1eca322b9ef35b4e8ba9b1cee1accc51434376 # Parent d7a865d2db068a21b0615565db8a78221b6199f3 patch 8.2.0098: exe stack length can be wrong without being detected Commit: https://github.com/vim/vim/commit/e31ee86859528a7ffe00405645547d494e522fa8 Author: Bram Moolenaar Date: Tue Jan 7 20:59:34 2020 +0100 patch 8.2.0098: exe stack length can be wrong without being detected Problem: Exe stack length can be wrong without being detected. Solution: Add a check when ABORT_ON_INTERNAL_ERROR is defined. diff --git a/src/autocmd.c b/src/autocmd.c --- a/src/autocmd.c +++ b/src/autocmd.c @@ -1827,6 +1827,7 @@ apply_autocmds_group( 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 @@ -2021,6 +2022,7 @@ apply_autocmds_group( // name and lnum are filled in later estack_push(ETYPE_AUCMD, NULL, 0); + ESTACK_CHECK_SETUP #ifdef FEAT_EVAL save_current_sctx = current_sctx; @@ -2124,6 +2126,7 @@ apply_autocmds_group( 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; diff --git a/src/buffer.c b/src/buffer.c --- a/src/buffer.c +++ b/src/buffer.c @@ -5287,6 +5287,7 @@ chk_modeline( #ifdef FEAT_EVAL sctx_T save_current_sctx; #endif + ESTACK_CHECK_DECLARATION prev = -1; for (s = ml_get(lnum); *s != NUL; ++s) @@ -5330,6 +5331,7 @@ chk_modeline( // prepare for emsg() estack_push(ETYPE_MODELINE, (char_u *)"modelines", lnum); + ESTACK_CHECK_SETUP end = FALSE; while (end == FALSE) @@ -5390,6 +5392,7 @@ chk_modeline( s = e + 1; // advance to next part } + ESTACK_CHECK_NOW estack_pop(); vim_free(linecopy); } diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -645,6 +645,7 @@ do_cmdline( # 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 @@ -1260,6 +1261,7 @@ do_cmdline( 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' @@ -1284,6 +1286,7 @@ do_cmdline( vim_free(p); } vim_free(SOURCING_NAME); + ESTACK_CHECK_NOW estack_pop(); } diff --git a/src/macros.h b/src/macros.h --- a/src/macros.h +++ b/src/macros.h @@ -344,3 +344,15 @@ #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 diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -3086,16 +3086,19 @@ exe_pre_commands(mparm_T *parmp) 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; @@ -3111,6 +3114,7 @@ exe_pre_commands(mparm_T *parmp) exe_commands(mparm_T *parmp) { int i; + ESTACK_CHECK_DECLARATION /* * We start commands on line 0, make "vim +/pat file" match a @@ -3121,6 +3125,7 @@ exe_commands(mparm_T *parmp) 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; @@ -3131,6 +3136,7 @@ exe_commands(mparm_T *parmp) if (parmp->cmds_tofree[i]) vim_free(parmp->commands[i]); } + ESTACK_CHECK_NOW estack_pop(); #ifdef FEAT_EVAL current_sctx.sc_sid = 0; @@ -3340,12 +3346,14 @@ process_env( #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; @@ -3355,6 +3363,7 @@ process_env( #endif do_cmdline_cmd(initstr); + ESTACK_CHECK_NOW estack_pop(); #ifdef FEAT_EVAL current_sctx = save_current_sctx; diff --git a/src/map.c b/src/map.c --- a/src/map.c +++ b/src/map.c @@ -1918,10 +1918,12 @@ check_map_keycodes(void) 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 @@ -1978,6 +1980,7 @@ check_map_keycodes(void) if (bp == NULL) break; } + ESTACK_CHECK_NOW estack_pop(); } diff --git a/src/scriptfile.c b/src/scriptfile.c --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1099,6 +1099,7 @@ do_source( proftime_T wait_start; #endif int trigger_source_post = FALSE; + ESTACK_CHECK_DECLARATION p = expand_env_save(fname); if (p == NULL) @@ -1216,6 +1217,7 @@ do_source( // Keep the sourcing name/lnum, for recursive calls. estack_push(ETYPE_SCRIPT, fname_exp, 0); + ESTACK_CHECK_SETUP #ifdef STARTUPTIME if (time_fd != NULL) @@ -1355,6 +1357,7 @@ do_source( if (got_int) emsg(_(e_interr)); + ESTACK_CHECK_NOW estack_pop(); if (p_verbose > 1) { diff --git a/src/spellfile.c b/src/spellfile.c --- a/src/spellfile.c +++ b/src/spellfile.c @@ -353,6 +353,7 @@ spell_load_file( int c = 0; int res; int did_estack_push = FALSE; + ESTACK_CHECK_DECLARATION fd = mch_fopen((char *)fname, "r"); if (fd == NULL) @@ -393,6 +394,7 @@ spell_load_file( // Set sourcing_name, so that error messages mention the file name. estack_push(ETYPE_SPELL, fname, 0); + ESTACK_CHECK_SETUP did_estack_push = TRUE; /* @@ -581,7 +583,10 @@ endOK: if (fd != NULL) fclose(fd); if (did_estack_push) + { + ESTACK_CHECK_NOW estack_pop(); + } return lp; } diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -793,6 +793,7 @@ call_user_func( 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) @@ -969,6 +970,7 @@ call_user_func( } estack_push_ufunc(ETYPE_UFUNC, fp, 1); + ESTACK_CHECK_SETUP if (p_verbose >= 12) { ++no_wait_return; @@ -1115,6 +1117,7 @@ call_user_func( --no_wait_return; } + ESTACK_CHECK_NOW estack_pop(); current_sctx = save_current_sctx; #ifdef FEAT_PROFILE diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -743,6 +743,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 98, +/**/ 97, /**/ 96,