On Fri, Aug 22, 2025 at 2:58 PM Chet Ramey <chet.ra...@case.edu> wrote: > > The idea is that the application's signal handler gets to decide what to > do. In most cases, it will longjmp back to some processing loop or exit. > The signal event handler provides responsiveness in the case where the > application simply sets a flag in a signal handler (like bash or gdb, > for instance) and doesn't want to wait for additional character input > before handling it. > > Now, if the application's signal handler returns after an interrupted read, > and there isn't any signal hook, readline has to decide what to do: should > it continue from where it left off, as the application appears to indicate, > or should it abort the current operation? There are some states where > readline has to abort, since it's already deallocated resources. Those > states are already identified, but the code only calls _rl_abort_internal() > when in callback mode.
Thanks very much for the explanation. I guess other places where RL_CHECK_SIGNALS() may be invoked while in one of those identified states should perform the same check and abort as well? For example, a SIGINT during redisplay currently causes a UAF: strace -e fd=2 -e write --inject=write:signal=INT:when=1 -Z \ -E PS1= -E INPUTRC=/ ./bash --norc -in <<< $'\cR' write(2, "(reverse-i-search)`': ", 22) = ? ERESTARTSYS --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} --- --- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=402, si_uid=1000} --- ================================================================= ==402==ERROR: AddressSanitizer: heap-use-after-free ... WRITE of size 4 at 0xe74ef25e037c thread T0 #0 0xab3ed9e57840 in _rl_search_getchar isearch.c:322:18 #1 0xab3ed9e57594 in rl_search_history isearch.c:927:11 ... freed by thread T0 here: #2 0xab3ed9e572c4 in _rl_scxt_dispose isearch.c:127:3 #3 0xab3ed9e6c1a4 in _rl_isearch_cleanup isearch.c:899:3 #4 0xab3ed9e9fde0 in _rl_state_sigcleanup signals.c:599:5 #5 0xab3ed9e9ff24 in rl_free_line_state signals.c:616:5 #6 0xab3ed9e9e2f0 in _rl_handle_signal signals.c:221:7 #7 0xab3ed9e9e004 in _rl_signal_handler signals.c:152:5 #8 0xab3ed9ea0120 in _rl_release_sigint signals.c:680:5 #9 0xab3ed9e83c54 in rl_redisplay display.c:1712:3 #10 0xab3ed9e98c68 in rl_message display.c:3179:3 #11 0xab3ed9e6c0e8 in rl_display_search isearch.c:197:3 #12 0xab3ed9e5753c in rl_search_history isearch.c:917:3 ... There is also a similar issue during readstr: strace -e fd=2 -e write --inject=write:signal=INT:when=2 -Z \ -E PS1= -E INPUTRC=/ ./bash --norc -in <<< $'\exundo' !write(2, "u", 1) = ? ERESTARTSYS --- SIGINT {si_signo=SIGINT, si_code=SI_KERNEL} --- u--- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=432, si_uid=1000} --- ================================================================= ==432==ERROR: AddressSanitizer: heap-use-after-free ... READ of size 4 at 0xf4e0309e29c8 thread T0 #0 0xc2fda7d03d44 in _rl_readstr_getchar text.c:2078:21 #1 0xc2fda7d05154 in _rl_read_command_name text.c:2330:11 #2 0xc2fda7d04da8 in rl_execute_named_command text.c:2372:13 ... freed by thread T0 here: #2 0xc2fda7d03160 in _rl_rscxt_dispose text.c:1989:3 #3 0xc2fda7d035a4 in _rl_readstr_cleanup text.c:2043:3 #4 0xc2fda7d03c2c in _rl_readstr_sigcleanup text.c:2070:11 #5 0xc2fda7ccfeb8 in _rl_state_sigcleanup signals.c:603:5 #6 0xc2fda7ccff24 in rl_free_line_state signals.c:616:5 #7 0xc2fda7cce2f0 in _rl_handle_signal signals.c:221:7 #8 0xc2fda7cce004 in _rl_signal_handler signals.c:152:5 #9 0xc2fda7cd0120 in _rl_release_sigint signals.c:680:5 #10 0xc2fda7cb3c54 in rl_redisplay display.c:1712:3 #11 0xc2fda7d04d48 in _rl_readstr_dispatch text.c:2206:3 #12 0xc2fda7d051a4 in _rl_read_command_name text.c:2342:11 #13 0xc2fda7d04da8 in rl_execute_named_command text.c:2372:13 ...