diff options
| author | Roberto I <roberto@inf.puc-rio.br> | 2026-02-18 13:24:04 -0300 |
|---|---|---|
| committer | Roberto I <roberto@inf.puc-rio.br> | 2026-02-18 13:24:04 -0300 |
| commit | 10eb89d1141dc528806b32401e408e36fb2f3bf5 (patch) | |
| tree | c1d33a4c965758cd9b39ad2fdc3c181295a05ab8 /lutf8lib.c | |
| parent | 7c40c5edb2364745bf0add6feb02c7c90dfbae3e (diff) | |
| download | lua-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.c | 5 |
1 files changed, 4 insertions, 1 deletions
| @@ -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 | } |
