On Sun, Aug 17, 2025 at 2:04â¯PM penguin p <tgc...@gmail.com> wrote: > [...] > 5 bash 0x100ca36e8 update_line + 9096 (display.c:2133) > 6 bash 0x100c9b2dc rl_redisplay + 27264 (display.c:1368) > 7 bash 0x100ca8924 rl_clear_message + 128 (display.c:3194) > 8 bash 0x100c93ab0 _rl_isearch_fini + 2396 (isearch.c:311) > 9 bash 0x100c930ec _rl_isearch_cleanup + 68 (isearch.c:893) > 10 bash 0x100cad22c _rl_state_sigcleanup + 180 (signals.c:599) > 11 bash 0x100cad388 rl_free_line_state + 92 (signals.c:616) > 12 bash 0x100cabbd8 _rl_handle_signal + 824 (signals.c:221) > 13 bash 0x100cab890 _rl_signal_handler + 340 (signals.c:152) > 14 bash 0x100cad500 _rl_release_sigint + 156 (signals.c:680) > 15 bash 0x100c9d340 rl_redisplay + 35556 (display.c:1712) > 16 bash 0x100ca8924 rl_clear_message + 128 (display.c:3194) > 17 bash 0x100c93ab0 _rl_isearch_fini + 2396 (isearch.c:311) > 18 bash 0x100c930ec _rl_isearch_cleanup + 68 (isearch.c:893) > 19 bash 0x100c8a330 rl_search_history + 516 (isearch.c:936) > [...]
So while _rl_isearch_fini is being executed due to normal search termination, it gets called again from a signal handler. This is reproducible by, for example, injecting a SIGINT using strace: strace -o /dev/null --trace-fds 2 -e write \ --inject=write:signal=SIGINT:when=7 \ -E INPUTRC=/ -E HISTFILE= -E ASAN_OPTIONS=detect_leaks=0 \ ./bash --norc -in <<< $'\cRXY' Which shows the following from UBSAN: display.c:2901:52: runtime error: null pointer passed as argument 2, which is declared to never be null /usr/include/string.h:65:33: note: nonnull attribute specified here SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior display.c:2901:52 And from ASAN: ERROR: AddressSanitizer: heap-use-after-free on address ... READ of size 8 at 0xe395f71e0318 thread T0 #0 0xc28098436c84 in _rl_scxt_dispose isearch.c:123:3 #1 0xc2809844be24 in _rl_isearch_cleanup isearch.c:915:3 #2 0xc2809843745c in rl_search_history isearch.c:961:11 #3 0xc280984370a4 in rl_reverse_search_history isearch.c:135:11 ... freed by thread T0 here: #2 0xc28098437034 in _rl_scxt_dispose isearch.c:127:3 #3 0xc2809844be24 in _rl_isearch_cleanup isearch.c:915:3 #4 0xc2809847fa90 in _rl_state_sigcleanup signals.c:599:5 #5 0xc2809847fbd4 in rl_free_line_state signals.c:616:5 #6 0xc2809847dfa0 in _rl_handle_signal signals.c:221:7 #7 0xc2809847dcb4 in _rl_signal_handler signals.c:152:5 #8 0xc2809847fdd0 in _rl_release_sigint signals.c:680:5 #9 0xc28098463904 in rl_redisplay display.c:1712:3 #10 0xc28098478b60 in rl_clear_message display.c:3194:3 #11 0xc2809844d300 in _rl_isearch_fini isearch.c:311:3 #12 0xc2809844be14 in _rl_isearch_cleanup isearch.c:914:5 #13 0xc2809843745c in rl_search_history isearch.c:961:11 ... The following change should fix this. --- Ref: https://lists.gnu.org/archive/html/bug-bash/2025-08/msg00080.html lib/readline/isearch.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/readline/isearch.c b/lib/readline/isearch.c index 241e2ee0..104835d9 100644 --- a/lib/readline/isearch.c +++ b/lib/readline/isearch.c @@ -910,13 +910,15 @@ opcode_dispatch: int _rl_isearch_cleanup (_rl_search_cxt *cxt, int r) { + /* Unset RL_STATE_ISEARCH now to avoid _rl_state_sigcleanup calling us if a + signal is received while _rl_isearch_fini is calling rl_clear_message */ + RL_UNSETSTATE(RL_STATE_ISEARCH); + if (r >= 0) _rl_isearch_fini (cxt); _rl_scxt_dispose (cxt, 0); _rl_iscxt = 0; - RL_UNSETSTATE(RL_STATE_ISEARCH); - return (r != 0); } -- 2.50.1