@samitouri / QOSamiQemu / commits / 12d8ee9d53

hw/usb/xhci: clamp interval exponent to avoid UB shift in xhci_init_epctx()

The xHCI endpoint context dword 0 bits 23:16 ("Interval") are written by the guest and passed directly as the shift amount in: epctx->interval = 1 << ((ctx[0] >> 16) & 0xff); The shift amount can be 0-255. Shifting a 32-bit `int` left by >= 32 is undefined behaviour under C11 §6.5.7p4. With UBSan (halt_on_error=1) this causes QEMU to abort; with aggressive compiler optimisations that assume UB is unreachable the result is unpredictable. Clamp the exponent to [0, 18] with MIN() before the shift, and use `1u` (unsigned) to avoid shifting a signed integer. The xHCI specification defines a maximum meaningful Interval value of 18 for most endpoint types; thus clamping to 18 is a safe fix that preserves the full unsigned 32-bit range for any compliant value. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3703 Reported-by: Feifan Qian <bea1e@proton.me> Signed-off-by: Feifan Qian <bea1e@proton.me> [thuth: Clamp to 18 instead of 31] Signed-off-by: Thomas Huth <thuth@redhat.com>

Feifan Qian committed Apr 24, 2026 at 13:20 UTC 12d8ee9d5358cd8cdd2c2193081b4d7fea4b6098
1 file changed +1 -1
hw/usb/hcd-xhci.c
+1 -1
@@ -1121,7 +1121,7 @@ static void xhci_init_epctx(XHCIEPContext *epctx,
1121 epctx->ring.ccs = ctx[2] & 1;
1122 }
1123
1124 - epctx->interval = 1 << ((ctx[0] >> 16) & 0xff);
1124 + epctx->interval = 1u << MIN((ctx[0] >> 16) & 0xffu, 18u);
1125 }
1126
1127 static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,