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: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/2082>
This commit is contained in:
Wismill
2026-03-14 20:10:37 +02:00
committed by Enrico Weigelt
parent d0e2967eab
commit dc79426c04
2 changed files with 3 additions and 2 deletions

View File

@@ -3794,7 +3794,8 @@ XkbAssembleNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply rep, x_rpcbu
XkbKeyTypePtr type = xkb->map->types; XkbKeyTypePtr type = xkb->map->types;
for (i = 0; i < rep.nTypes; i++, type++) { 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); x_rpcbuf_pad(rpcbuf);

View File

@@ -1046,7 +1046,7 @@ _XkbCopyClientMap(XkbDescPtr src, XkbDescPtr dst)
if (dtype->num_levels && dtype->level_names && if (dtype->num_levels && dtype->level_names &&
i < dst->map->num_types) i < dst->map->num_types)
free(dtype->level_names); free(dtype->level_names);
dtype->num_levels = 0; dtype->num_levels = stype->num_levels;
dtype->level_names = NULL; dtype->level_names = NULL;
} }