diff options
| author | Roberto I <roberto@inf.puc-rio.br> | 2026-07-22 15:07:52 -0300 |
|---|---|---|
| committer | Roberto I <roberto@inf.puc-rio.br> | 2026-07-22 15:07:52 -0300 |
| commit | af19891bce064a625deeea0fa3d0005f6e22842a (patch) | |
| tree | 9d907160d21e74a2aa90eacd560aed6a73589bcd /lutf8lib.c | |
| parent | 8511e90b7df5daf139aba290b9c9c1595927e7b3 (diff) | |
| download | lua-af19891bce064a625deeea0fa3d0005f6e22842a.tar.gz lua-af19891bce064a625deeea0fa3d0005f6e22842a.tar.bz2 lua-af19891bce064a625deeea0fa3d0005f6e22842a.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 'lutf8lib.c')
| -rw-r--r-- | lutf8lib.c | 4 |
1 files changed, 3 insertions, 1 deletions
| @@ -65,6 +65,8 @@ static const char *utf8_decode (const char *s, utfint *val, int strict) { | |||
| 65 | utfint res = 0; /* final result */ | 65 | utfint res = 0; /* final result */ |
| 66 | if (c < 0x80) /* ascii? */ | 66 | if (c < 0x80) /* ascii? */ |
| 67 | res = c; | 67 | res = c; |
| 68 | else if (c >= 0xfe) /* c >= 1111 1110b ? */ | ||
| 69 | return NULL; /* would need six or more continuation bytes */ | ||
| 68 | else { | 70 | else { |
| 69 | int count = 0; /* to count number of continuation bytes */ | 71 | int count = 0; /* to count number of continuation bytes */ |
| 70 | for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */ | 72 | for (; c & 0x40; c <<= 1) { /* while it needs continuation bytes... */ |
| @@ -74,7 +76,7 @@ static const char *utf8_decode (const char *s, utfint *val, int strict) { | |||
| 74 | res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ | 76 | res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ |
| 75 | } | 77 | } |
| 76 | res |= ((utfint)(c & 0x7F) << (count * 5)); /* add first byte */ | 78 | res |= ((utfint)(c & 0x7F) << (count * 5)); /* add first byte */ |
| 77 | if (count > 5 || res > MAXUTF || res < limits[count]) | 79 | if (res > MAXUTF || res < limits[count]) |
| 78 | return NULL; /* invalid byte sequence */ | 80 | return NULL; /* invalid byte sequence */ |
| 79 | s += count; /* skip continuation bytes read */ | 81 | s += count; /* skip continuation bytes read */ |
| 80 | } | 82 | } |
