From: Foxe Chen Date: Sat, 19 Apr 2025 09:25:18 +0000 (+0200) Subject: patch 9.1.1324: undefined behaviour if X11 connection dies X-Git-Tag: v9.1.1324^0 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6924eb81f4e69726f59eaa0c121b7442343d770d;p=thirdparty%2Fvim.git 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 Signed-off-by: Christian Brabandt --- diff --git a/src/main.c b/src/main.c index 9a862c4be9..31494e3e8e 100644 --- a/src/main.c +++ b/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); diff --git a/src/version.c b/src/version.c index db77e4538f..e3b55fa94a 100644 --- a/src/version.c +++ b/src/version.c @@ -704,6 +704,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1324, /**/ 1323, /**/