Don't modify kbd_fetch_ptr in x_delete_selection_requests (bug#80863)

This code may be called from within the loop in process_special_events
which assumed kbd_fetch_ptr remains unchanged.  This caused a buffer
underflow which resulted in the entire kbd buffer being replayed.

* src/xterm.c (x_delete_selection_requests): Simply clear deleted
events rather than rotating the kbd buffer.
This commit is contained in:
Pip Cet 2026-04-21 13:08:36 +00:00
parent 19d1834ce0
commit 6a19ab9cce

View file

@ -31784,7 +31784,6 @@ static void
x_delete_selection_requests (struct x_display_info *dpyinfo)
{
union buffered_input_event *event;
int moved_events;
for (event = kbd_fetch_ptr; event != kbd_store_ptr;
event = X_NEXT_KBD_EVENT (event))
@ -31795,25 +31794,8 @@ x_delete_selection_requests (struct x_display_info *dpyinfo)
if (SELECTION_EVENT_DPYINFO (&event->sie) != dpyinfo)
continue;
/* Remove the event from the fifo buffer before processing;
otherwise swallow_events called recursively could see it
and process it again. To do this, we move the events
between kbd_fetch_ptr and EVENT one slot to the right,
cyclically. */
if (event < kbd_fetch_ptr)
{
memmove (kbd_buffer + 1, kbd_buffer,
(event - kbd_buffer) * sizeof *kbd_buffer);
kbd_buffer[0] = kbd_buffer[KBD_BUFFER_SIZE - 1];
moved_events = kbd_buffer + KBD_BUFFER_SIZE - 1 - kbd_fetch_ptr;
}
else
moved_events = event - kbd_fetch_ptr;
memmove (kbd_fetch_ptr + 1, kbd_fetch_ptr,
moved_events * sizeof *kbd_fetch_ptr);
kbd_fetch_ptr = X_NEXT_KBD_EVENT (kbd_fetch_ptr);
EVENT_INIT (event->ie);
event->ie.kind = NO_EVENT;
/* `detect_input_pending' will then recompute whether or not
pending input events exist. */