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) ();
        }
     }

Reply via email to