On Wed, Aug 20, 2025 at 5:31 PM Chet Ramey <chet.ra...@case.edu> wrote: > > On 8/20/25 3:36 PM, Chet Ramey wrote: > > >> ================================================================= > >> ==1078506==ERROR: AddressSanitizer: heap-use-after-free on address > >> 0x7c315f7e217c at pc 0x55bc1d03b545 bp 0x7ffdbdb3c920 sp 0x7ffdbdb3c910 > >> WRITE of size 4 at 0x7c315f7e217c thread T0 > >> #0 0x55bc1d03b544 in _rl_search_getchar /home/arch/works/bash/lib/ > >> readline/isearch.c:322 > > > > This is probably the same issue Grisha identified initially: handling > > SIGINT in rl_read_key ends up invalidating the search context, and then > > rl_read_key returns -1, which _rl_search_getchar tries to assign to > > cxt->c_lastc. But I'd like to be able to reproduce it. > > The real issue is that readline, when reading from its standard input, > which is the keyboard in the vast majority of situations, does not > believe that read(2) can both succeed (return value > 0) *and* get a > signal before it returns to user mode without setting errno. You simply > cannot type that fast, since read returns after reading one character. > You either need to inject it into the input artificially or hit the process > with SIGINT from another process with exquisitely precise timing. > > I'll have to think about what to do about that. >
So AFAICT, the case where everything works fine is: upon a SIGINT in rl_getc, the RL_CHECK_SIGNALS() invocation is followed by a call to *rl_signal_event_hook which, in bash, ends up calling throw_to_top_level. But most uses of RL_CHECK_SIGNALS() are _not_ followed by a call to *rl_signal_event_hook, so I don't really understand how that can work: if a SIGINT has been received, cleanup code will be executed that leaves whatever readline was doing in a state that it cannot continue from. An exception is the completion code that checks the value of _rl_complete_display_matches_interrupt. Would it work to call *rl_signal_event_hook in more (or all?) places where RL_CHECK_SIGNALS() is used? Adding it to rl_read_key seems to resolve the OP's reported issue: diff --git a/lib/readline/input.c b/lib/readline/input.c index 3383edb6..6885e76d 100644 --- a/lib/readline/input.c +++ b/lib/readline/input.c @@ -827,6 +827,8 @@ rl_read_key (void) c = (*rl_getc_function) (rl_instream); /* fprintf(stderr, "rl_read_key: calling RL_CHECK_SIGNALS: _rl_caught_signal = %d\r\n", _rl_caught_signal); */ RL_CHECK_SIGNALS (); + if (rl_signal_event_hook) + (*rl_signal_event_hook) (); } }