aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto I <roberto@inf.puc-rio.br>2026-07-22 15:07:52 -0300
committerRoberto I <roberto@inf.puc-rio.br>2026-07-22 15:07:52 -0300
commitaf19891bce064a625deeea0fa3d0005f6e22842a (patch)
tree9d907160d21e74a2aa90eacd560aed6a73589bcd
parent8511e90b7df5daf139aba290b9c9c1595927e7b3 (diff)
downloadlua-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.
-rw-r--r--lutf8lib.c4
1 files changed, 3 insertions, 1 deletions
diff --git a/lutf8lib.c b/lutf8lib.c
index 3a5b9bc3..e41a8255 100644
--- a/lutf8lib.c
+++ b/lutf8lib.c
@@ -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 }