keysym: properly handle overflow in 0x keysym names
Relatedly, strtoul allows a lot of unwanted stuff (spaces, +/- sign, thousand seperators), we really ought not use it. But that's for another time. Signed-off-by: Ran Benita <ran@unusedvar.com>master
parent
1638409b22
commit
1c0e28ad26
16
src/keysym.c
16
src/keysym.c
|
@ -96,7 +96,7 @@ xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags)
|
||||||
{
|
{
|
||||||
const struct name_keysym *entry = NULL;
|
const struct name_keysym *entry = NULL;
|
||||||
char *tmp;
|
char *tmp;
|
||||||
xkb_keysym_t val;
|
unsigned long val;
|
||||||
bool icase = (flags & XKB_KEYSYM_CASE_INSENSITIVE);
|
bool icase = (flags & XKB_KEYSYM_CASE_INSENSITIVE);
|
||||||
|
|
||||||
if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE)
|
if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE)
|
||||||
|
@ -174,24 +174,28 @@ xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*name == 'U' || (icase && *name == 'u')) {
|
if (*name == 'U' || (icase && *name == 'u')) {
|
||||||
|
errno = 0;
|
||||||
val = strtoul(&name[1], &tmp, 16);
|
val = strtoul(&name[1], &tmp, 16);
|
||||||
if (tmp && *tmp != '\0')
|
if ((tmp && *tmp != '\0') || errno != 0)
|
||||||
return XKB_KEY_NoSymbol;
|
return XKB_KEY_NoSymbol;
|
||||||
|
|
||||||
if (val < 0x20 || (val > 0x7e && val < 0xa0))
|
if (val < 0x20 || (val > 0x7e && val < 0xa0))
|
||||||
return XKB_KEY_NoSymbol;
|
return XKB_KEY_NoSymbol;
|
||||||
if (val < 0x100)
|
if (val < 0x100)
|
||||||
return val;
|
return (xkb_keysym_t) val;
|
||||||
if (val > 0x10ffff)
|
if (val > 0x10ffff)
|
||||||
return XKB_KEY_NoSymbol;
|
return XKB_KEY_NoSymbol;
|
||||||
return val | 0x01000000;
|
return (xkb_keysym_t) val | 0x01000000;
|
||||||
}
|
}
|
||||||
else if (name[0] == '0' && (name[1] == 'x' || (icase && name[1] == 'X'))) {
|
else if (name[0] == '0' && (name[1] == 'x' || (icase && name[1] == 'X'))) {
|
||||||
|
errno = 0;
|
||||||
val = strtoul(&name[2], &tmp, 16);
|
val = strtoul(&name[2], &tmp, 16);
|
||||||
if (tmp && *tmp != '\0')
|
if ((tmp && *tmp != '\0') || errno != 0)
|
||||||
|
return XKB_KEY_NoSymbol;
|
||||||
|
if (val > UINT32_MAX)
|
||||||
return XKB_KEY_NoSymbol;
|
return XKB_KEY_NoSymbol;
|
||||||
|
|
||||||
return val;
|
return (xkb_keysym_t) val;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Stupid inconsistency between the headers and XKeysymDB: the former has
|
/* Stupid inconsistency between the headers and XKeysymDB: the former has
|
||||||
|
|
|
@ -145,6 +145,10 @@ main(void)
|
||||||
assert(test_string("THORN", 0x00de));
|
assert(test_string("THORN", 0x00de));
|
||||||
assert(test_string("Thorn", 0x00de));
|
assert(test_string("Thorn", 0x00de));
|
||||||
assert(test_string("thorn", 0x00fe));
|
assert(test_string("thorn", 0x00fe));
|
||||||
|
/* Max keysym. */
|
||||||
|
assert(test_string("0xffffffff", 0xffffffff));
|
||||||
|
/* Outside range. */
|
||||||
|
assert(test_string("0x100000000", XKB_KEY_NoSymbol));
|
||||||
|
|
||||||
assert(test_keysym(0x1008FF56, "XF86Close"));
|
assert(test_keysym(0x1008FF56, "XF86Close"));
|
||||||
assert(test_keysym(0x0, "NoSymbol"));
|
assert(test_keysym(0x0, "NoSymbol"));
|
||||||
|
|
Loading…
Reference in New Issue