aboutsummaryrefslogtreecommitdiff
path: root/lutf8lib.c
diff options
context:
space:
mode:
authorRoberto I <roberto@inf.puc-rio.br>2026-02-18 13:24:04 -0300
committerRoberto I <roberto@inf.puc-rio.br>2026-02-18 13:24:04 -0300
commit10eb89d1141dc528806b32401e408e36fb2f3bf5 (patch)
treec1d33a4c965758cd9b39ad2fdc3c181295a05ab8 /lutf8lib.c
parent7c40c5edb2364745bf0add6feb02c7c90dfbae3e (diff)
downloadlua-10eb89d1141dc528806b32401e408e36fb2f3bf5.tar.gz
lua-10eb89d1141dc528806b32401e408e36fb2f3bf5.tar.bz2
lua-10eb89d1141dc528806b32401e408e36fb2f3bf5.zip
BUG: shift overflow in utf-8 decode
An initial byte \xFF will ask for 7 continuation bytes, and then the shift by (count * 5) will try to shift 35 bits.
Diffstat (limited to '')
-rw-r--r--lutf8lib.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/lutf8lib.c b/lutf8lib.c
index b7f3fe1e..73f0e49b 100644
--- a/lutf8lib.c
+++ b/lutf8lib.c
@@ -56,6 +56,8 @@ static const char *utf8_decode (const char *s, l_uint32 *val, int strict) {
56 l_uint32 res = 0; /* final result */ 56 l_uint32 res = 0; /* final result */
57 if (c < 0x80) /* ASCII? */ 57 if (c < 0x80) /* ASCII? */
58 res = c; 58 res = c;
59 else if (c >= 0xfe) /* c >= 1111 1110b ? */
60 return NULL; /* would need six or more continuation bytes */
59 else { 61 else {
60 int count = 0; /* to count number of continuation bytes */ 62 int count = 0; /* to count number of continuation bytes */
61 for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */ 63 for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */
@@ -64,8 +66,9 @@ static const char *utf8_decode (const char *s, l_uint32 *val, int strict) {
64 return NULL; /* invalid byte sequence */ 66 return NULL; /* invalid byte sequence */
65 res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ 67 res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
66 } 68 }
69 lua_assert(count <= 5);
67 res |= ((l_uint32)(c & 0x7F) << (count * 5)); /* add first byte */ 70 res |= ((l_uint32)(c & 0x7F) << (count * 5)); /* add first byte */
68 if (count > 5 || res > MAXUTF || res < limits[count]) 71 if (res > MAXUTF || res < limits[count])
69 return NULL; /* invalid byte sequence */ 72 return NULL; /* invalid byte sequence */
70 s += count; /* skip continuation bytes read */ 73 s += count; /* skip continuation bytes read */
71 } 74 }