scanner: allow for a zero terminated string as keymap
authorPeter Hutterer <peter.hutterer@who-t.net>
Tue, 2 May 2023 04:15:55 +0000 (14:15 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Thu, 4 May 2023 23:57:23 +0000 (09:57 +1000)
As the documentation for xkb_keymap_new_from_buffer() states, the "input string
does not have to be zero-terminated". The actual implementation however failed
with "unrecognized token/syntax error" when it encountered a null byte.

Fix this by allowing a null byte at the last position of the buffer. Anything
else is likely a client error anyway.

Fixes #307

src/keymap.c
test/buffercomp.c

index d2baf94..0291aed 100644 (file)
@@ -194,6 +194,10 @@ xkb_keymap_new_from_buffer(struct xkb_context *ctx,
     if (!keymap)
         return NULL;
 
+    /* Allow a zero-terminated string as a buffer */
+    if (length > 0 && buffer[length - 1] == '\0')
+        length--;
+
     if (!ops->keymap_new_from_string(keymap, buffer, length)) {
         xkb_keymap_unref(keymap);
         return NULL;
index 12b67fe..9a76036 100644 (file)
@@ -46,29 +46,33 @@ main(int argc, char *argv[])
     original = test_read_file(DATA_PATH);
     assert(original);
 
-    keymap = test_compile_buffer(ctx, original, strlen(original));
-    assert(keymap);
+    /* Load a prebuild keymap, once without, once with the trailing \0 */
+    for (int i = 0; i <= 1; i++) {
+        keymap = test_compile_buffer(ctx, original, strlen(original) + i);
+        assert(keymap);
 
-    dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT);
-    assert(dump);
+        dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT);
+        assert(dump);
 
-    if (!streq(original, dump)) {
-        fprintf(stderr,
-                "round-trip test failed: dumped map differs from original\n");
-        fprintf(stderr, "path to original file: %s\n",
-                test_get_path(DATA_PATH));
-        fprintf(stderr, "length: dumped %lu, original %lu\n",
-                (unsigned long) strlen(dump),
-                (unsigned long) strlen(original));
-        fprintf(stderr, "dumped map:\n");
-        fprintf(stderr, "%s\n", dump);
-        fflush(stderr);
-        assert(0);
+        if (!streq(original, dump)) {
+            fprintf(stderr,
+                    "round-trip test failed: dumped map differs from original\n");
+            fprintf(stderr, "path to original file: %s\n",
+                    test_get_path(DATA_PATH));
+            fprintf(stderr, "length: dumped %lu, original %lu\n",
+                    (unsigned long) strlen(dump),
+                    (unsigned long) strlen(original));
+            fprintf(stderr, "dumped map:\n");
+            fprintf(stderr, "%s\n", dump);
+            fflush(stderr);
+            assert(0);
+        }
+
+        free(dump);
+        xkb_keymap_unref(keymap);
     }
 
     free(original);
-    free(dump);
-    xkb_keymap_unref(keymap);
 
     /* Make sure we can't (falsely claim to) compile an empty string. */
     keymap = test_compile_buffer(ctx, "", 0);