From dc79426c04b4990de9d3aa21c7a72228377bdfdd Mon Sep 17 00:00:00 2001 From: Wismill Date: Sat, 14 Mar 2026 20:10:37 +0200 Subject: [PATCH] xkb: Fix key type without level names in XkbCopyKeymap A key type that has no level names is legit. Before this commit, `XkbCopyKeymap` would make such level inconsistent by setting its number of levels to 0 while keeping its map entries. It suffices to clear the names array. Fixed by copying the level count from the source type. WARNING: this will trigger an error in `XkbGetNames`, which worked before this commit only by chance. This is fixed in the next commit (squashed with this one). ------------------------------------------------------------------ xkb: Fix serialization of key type without level names Before this commit the count of key type level names was wrongly set in `XkbGetNames`: for key type without names, it was set to the level count, while it should be 0: - `XkbComputeGetNamesReplySize()` does not account key type without level names; - `XkbSendNames()` does not write any level entry for key types without level names. This causes a mismatch offset while parsing the response and its processing would ultimately fail. Fixed by setting the correct level name count: 0 if there is no level name, else the number of levels. Part-of: --- xkb/xkb.c | 3 ++- xkb/xkbUtils.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/xkb/xkb.c b/xkb/xkb.c index 2e9dcbf5de..1a443c80ff 100644 --- a/xkb/xkb.c +++ b/xkb/xkb.c @@ -3794,7 +3794,8 @@ XkbAssembleNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply rep, x_rpcbu XkbKeyTypePtr type = xkb->map->types; for (i = 0; i < rep.nTypes; i++, type++) { - x_rpcbuf_write_CARD8(rpcbuf, type->num_levels); + /* Either no name or all of them, even empty ones */ + x_rpcbuf_write_CARD8(rpcbuf, type->level_names ? type->num_levels : 0); } x_rpcbuf_pad(rpcbuf); diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index 68ee0b0888..ad71cd9cec 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -1046,7 +1046,7 @@ _XkbCopyClientMap(XkbDescPtr src, XkbDescPtr dst) if (dtype->num_levels && dtype->level_names && i < dst->map->num_types) free(dtype->level_names); - dtype->num_levels = 0; + dtype->num_levels = stype->num_levels; dtype->level_names = NULL; }