Subject: bug#76559: 31.0.50; [-O3 + PGTK] Crash when 'copying as kill'/'killing word'

From: Pip Cet <[email-masked]>
Date: Wed, 26 Feb 2025 18:47:51 +0000

"Iurie Marian" <[email-masked]> writes:

> Yes, it looks like Michael's changes have nothing to do with this bug,
> but these seem just to reveal some undefined behavior... idk. Btw, 
> just by commenting the line src/keyboard.c:11697, it is not crashing 
> anymore; maybe this could be a hint.
>
>> gcc --version
> gcc (Debian 12.2.0-14) 12.2.0
>
>> Can you check that 0x555555cf0b00 is a valid dpyinfo structure?
> (gdb) info locals
> event = 0x555555953aa0 <kbd_buffer+384>
> copy = {kind = SELECTION_REQUEST_EVENT, dpyinfo = 0x55c82260, requestor = 0x555555f93a80, selection = 0x45, target = 0x4d, property =
> 0x5e, time = 0}
> moved_events = <optimized out>
>
> (gdb) x 0x555555c82260
> 0x555555c82260: 0x00

Well, that only tells us the first byte is 0, which is probably correct.
Can you retry with x/64gx 0x555555c82260 (or the new address) so we see
some more data?

>> Can you run "ptype/o struct selection_input_event" [...]
>
> (gdb) ptype/o struct selection_input_event
> /* offset      |    size */  type = struct selection_input_event {
> /*      0: 0   |       4 */    enum event_kind kind : 16;
> /* XXX  6-byte hole      */

This is strange, but it looks like this may be a C undefined behavior
bug (or, less likely, an actual GCC bug).  If the event_kind bitfield is
listed with size 4, shouldn't the hole after it be listed with size 4,
not size 6?

Here's the code obtained by disass/s evq_flush which copies the relevant
part of the header:

3810	      *kbd_store_ptr = *event;
   0x00000000002f9f4c <+108>:	movd   %xmm0,(%rdx)
   0x00000000002f9f50 <+112>:	movdqa 0x20(%rsp),%xmm4
   0x00000000002f9f56 <+118>:	movdqa 0x10(%rsp),%xmm5
   0x00000000002f9f5c <+124>:	movq   %xmm1,0x4(%rdx)

The first movd (not movq or movdq!) copies four bytes containing the
event_kind.  The unaligned movq at +124 copies 8 bytes to bytes 4-11 of
the struct, which copies the low-order 4 bytes of the dpyinfo.

the code continues with:

   0x00000000002f9f61 <+129>:	mov    %rax,0x1094e0(%rip)        # 0x403448 <kbd_store_ptr>
   0x00000000002f9f68 <+136>:	sub    %rcx,%rax
   0x00000000002f9f6b <+139>:	sar    $0x6,%rax
   0x00000000002f9f6f <+143>:	mov    %r12,0x20(%rdx)
   0x00000000002f9f73 <+147>:	mov    %rbp,0x38(%rdx)
   0x00000000002f9f77 <+151>:	movups %xmm4,0x10(%rdx)
   0x00000000002f9f7b <+155>:	movups %xmm5,0x28(%rdx)

but, as far as I can tell, bytes 12-15 are never touched by this code.

Here's the corresponding code which copies the event structure:

327	      union buffered_input_event ev = evq->q[0];
   0x00000000002f9fee <+270>:	lea    0x19a64b(%rip),%rcx        # 0x494640 <event_q.lto_priv.0>
   0x00000000002f9ff5 <+277>:	mov    (%rcx),%rdi
   0x00000000002f9ff8 <+280>:	movd   (%rdi),%xmm0
   0x00000000002f9ffc <+284>:	movdqu 0x10(%rdi),%xmm2
   0x00000000002fa001 <+289>:	movdqu 0x28(%rdi),%xmm3
   0x00000000002fa006 <+294>:	movq   0x4(%rdi),%xmm1
   0x00000000002fa00b <+299>:	mov    0x20(%rdi),%r12
   0x00000000002fa00f <+303>:	mov    0x38(%rdi),%rbp
   0x00000000002fa013 <+307>:	pextrw $0x0,%xmm0,%r13d
   0x00000000002fa019 <+313>:	movaps %xmm2,0x20(%rsp)
   0x00000000002fa01e <+318>:	movaps %xmm3,0x10(%rsp)

Again, I see no code here which touches 0xc(%rdi) or the three bytes
after it.

But union buffered_input_event has no hole at bytes 12-15, only two of
its union members do.

So it seems this may be a bug with bitfield enums; it's not quite clear
to me why we're using one here, but it doesn't seem to be working as
intended.

Pip