From 5f2ac0de4798f2290620ff89ba86af171c45013c Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Sat, 18 Apr 2026 07:35:53 +1000 Subject: [PATCH] xkb: Fix off-by-one and NULL dereferences in _CheckSetOverlay() Off-by-one in rowUnder validation: the bounds check uses '>' instead of '>=' when comparing rWire->rowUnder against section->num_rows. Since num_rows is a count and valid indices are 0 to num_rows-1, rowUnder == num_rows passes the check but is one past the valid range. XkbAddGeomOverlayRow() uses this as an array index, causing an out-of-bounds read on section->rows[]. And throw in two alloc checks while we're at it. Assisted-by: Claude:claude-claude-opus-4-6 (cherry picked from commit ed19312c4bda0a8f66b236348ffc553e5d8d2a09) Part-of: --- xkb/xkb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/xkb/xkb.c b/xkb/xkb.c index ca9f2bcfd..94636d5e8 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -5359,6 +5359,8 @@ _CheckSetOverlay(char **wire_inout, xkbSetGeometryReq *req, } CHK_ATOM_ONLY(olWire->name); ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows); + if (!ol) + return BadAlloc; rWire = (xkbOverlayRowWireDesc *) &olWire[1]; for (r = 0; r < olWire->nRows; r++) { register int k; @@ -5368,12 +5370,14 @@ _CheckSetOverlay(char **wire_inout, xkbSetGeometryReq *req, if (!_XkbCheckRequestBounds(client, req, rWire, rWire + 1)) return BadLength; - if (rWire->rowUnder > section->num_rows) { + if (rWire->rowUnder >= section->num_rows) { client->errorValue = _XkbErrCode4(0x20, r, section->num_rows, rWire->rowUnder); return BadMatch; } row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys); + if (!row) + return BadAlloc; kWire = (xkbOverlayKeyWireDesc *) &rWire[1]; for (k = 0; k < rWire->nKeys; k++, kWire++) { if (!_XkbCheckRequestBounds(client, req, kWire, kWire + 1))