mirror of
https://github.com/vim/vim
synced 2025-07-16 01:01:58 +00:00
patch 9.1.1324: undefined behaviour if X11 connection dies
Problem: undefined behaviour if X11 connection dies Solution: call setjmp() before the main_loop() and restore x11 state if the X11 connection dies (Foxe Chen) fixes: #698 closes: #17142 Signed-off-by: Foxe Chen <chen.foxe@gmail.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
committed by
Christian Brabandt
parent
baa8c90cc0
commit
6924eb81f4
80
src/main.c
80
src/main.c
@ -449,6 +449,35 @@ main
|
||||
#endif // NO_VIM_MAIN
|
||||
#endif // PROTO
|
||||
|
||||
#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
|
||||
/*
|
||||
* Restore the state after a fatal X error.
|
||||
*/
|
||||
static void
|
||||
x_restore_state(void)
|
||||
{
|
||||
State = MODE_NORMAL;
|
||||
VIsual_active = FALSE;
|
||||
got_int = TRUE;
|
||||
need_wait_return = FALSE;
|
||||
global_busy = FALSE;
|
||||
exmode_active = 0;
|
||||
skip_redraw = FALSE;
|
||||
RedrawingDisabled = 0;
|
||||
no_wait_return = 0;
|
||||
vgetc_busy = 0;
|
||||
# ifdef FEAT_EVAL
|
||||
emsg_skip = 0;
|
||||
# endif
|
||||
emsg_off = 0;
|
||||
setmouse();
|
||||
settmode(TMODE_RAW);
|
||||
starttermcap();
|
||||
scroll_start();
|
||||
redraw_later_clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* vim_main2() is needed for FEAT_MZSCHEME, but we define it always to keep
|
||||
* things simple.
|
||||
@ -790,9 +819,28 @@ vim_main2(void)
|
||||
getout(1);
|
||||
}
|
||||
|
||||
// Execute any "+", "-c" and "-S" arguments.
|
||||
if (params.n_commands > 0)
|
||||
exe_commands(¶ms);
|
||||
#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
|
||||
// Temporarily set x_jump_env to here in case there is an X11 IO error,
|
||||
// because x_jump_env is only actually set in main_loop(), before
|
||||
// exe_commands(). May not be the best solution since commands passed via
|
||||
// the command line can be very broad like sourcing a file, in which case
|
||||
// an X IO error results in the command being partially done. In theory we
|
||||
// could use SETJMP in RealWaitForChar(), but the stack frame for that may
|
||||
// possibly exit and then LONGJMP is called on it.
|
||||
int jump_result = SETJMP(x_jump_env);
|
||||
|
||||
if (jump_result == 0)
|
||||
{
|
||||
#endif
|
||||
// Execute any "+", "-c" and "-S" arguments.
|
||||
if (params.n_commands > 0)
|
||||
exe_commands(¶ms);
|
||||
#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
|
||||
}
|
||||
else
|
||||
// Restore state and continue just like what main_loop() does.
|
||||
x_restore_state();
|
||||
#endif
|
||||
|
||||
// Must come before the may_req_ calls.
|
||||
starting = 0;
|
||||
@ -1242,30 +1290,10 @@ main_loop(
|
||||
#if defined(FEAT_X11) && defined(FEAT_XCLIPBOARD)
|
||||
// Setup to catch a terminating error from the X server. Just ignore
|
||||
// it, restore the state and continue. This might not always work
|
||||
// properly, but at least we don't exit unexpectedly when the X server
|
||||
// exits while Vim is running in a console.
|
||||
// properly, but at least we hopefully don't exit unexpectedly when the X
|
||||
// server exits while Vim is running in a console.
|
||||
if (!cmdwin && !noexmode && SETJMP(x_jump_env))
|
||||
{
|
||||
State = MODE_NORMAL;
|
||||
VIsual_active = FALSE;
|
||||
got_int = TRUE;
|
||||
need_wait_return = FALSE;
|
||||
global_busy = FALSE;
|
||||
exmode_active = 0;
|
||||
skip_redraw = FALSE;
|
||||
RedrawingDisabled = 0;
|
||||
no_wait_return = 0;
|
||||
vgetc_busy = 0;
|
||||
# ifdef FEAT_EVAL
|
||||
emsg_skip = 0;
|
||||
# endif
|
||||
emsg_off = 0;
|
||||
setmouse();
|
||||
settmode(TMODE_RAW);
|
||||
starttermcap();
|
||||
scroll_start();
|
||||
redraw_later_clear();
|
||||
}
|
||||
x_restore_state();
|
||||
#endif
|
||||
|
||||
clear_oparg(&oa);
|
||||
|
@ -704,6 +704,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1324,
|
||||
/**/
|
||||
1323,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user