keysym: fix underflow in binary searches
authorIsaac Freund <ifreund@ifreund.xyz>
Wed, 21 Apr 2021 22:37:03 +0000 (00:37 +0200)
committerRan Benita <ran@unusedvar.com>
Sun, 25 Apr 2021 09:25:58 +0000 (12:25 +0300)
This is hit when passing an empty string and XKB_KEYSYM_CASE_INSENSITIVE
to xkb_keysym_from_name currently if `(lo + hi) / 2` is 0 and `cmp < 0`,
causing mid to underflow and the the array access into name_to_keysym on
the next iteration of the loop to be out of bounds .

We *would* use ssize_t here as it is the appropriate type, but windows
unfortunately does not define it.

src/keysym.c
test/keysym.c

index 83a418e..bf49c63 100644 (file)
@@ -69,9 +69,9 @@ xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
         return -1;
     }
 
-    size_t lo = 0, hi = ARRAY_SIZE(keysym_to_name) - 1;
+    int32_t lo = 0, hi = ARRAY_SIZE(keysym_to_name) - 1;
     while (hi >= lo) {
-        size_t mid = (lo + hi) / 2;
+        int32_t mid = (lo + hi) / 2;
         if (ks > keysym_to_name[mid].keysym) {
             lo = mid + 1;
         } else if (ks < keysym_to_name[mid].keysym) {
@@ -155,9 +155,9 @@ xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags)
     * lower-case match is enough in this case.
     */
     else {
-        size_t lo = 0, hi = ARRAY_SIZE(name_to_keysym) - 1;
+        int32_t lo = 0, hi = ARRAY_SIZE(name_to_keysym) - 1;
         while (hi >= lo) {
-            size_t mid = (lo + hi) / 2;
+            int32_t mid = (lo + hi) / 2;
             int cmp = istrcmp(name, get_name(&name_to_keysym[mid]));
             if (cmp > 0) {
                 lo = mid + 1;
index 0c3ba9f..2c98c24 100644 (file)
@@ -189,6 +189,9 @@ main(void)
     assert(test_casestring("Thorn", 0x00fe));
     assert(test_casestring("thorn", 0x00fe));
 
+    assert(test_string("", XKB_KEY_NoSymbol));
+    assert(test_casestring("", XKB_KEY_NoSymbol));
+
     assert(test_utf8(XKB_KEY_y, "y"));
     assert(test_utf8(XKB_KEY_u, "u"));
     assert(test_utf8(XKB_KEY_m, "m"));