Incomplete attempt at making decoder honor len added by sjamaan on Thu Jul 9 11:22:04 2026
diff --git a/utf.c b/utf.c index d699ccf1..85c5f4dc 100644 --- a/utf.c +++ b/utf.c @@ -3172,7 +3172,7 @@ static const char lengths[] = { 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0 }; -static C_char *utf8_decode(C_char *buf, C_u32 *c, int *e) +static C_char *utf8_decode(C_char *buf, C_u32 *c, int *e, int slen) { static const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07}; static const uint32_t mins[] = {4194304, 0, 128, 2048, 65536}; @@ -3196,19 +3196,19 @@ static C_char *utf8_decode(C_char *buf, C_u32 *c, int *e) /* Assume a four-byte character and load four bytes. Unused bits are * shifted out. */ - *c = (C_u32)(s[0] & masks[len]) << 18; - *c |= (C_u32)(s[1] & 0x3f) << 12; - *c |= (C_u32)(s[2] & 0x3f) << 6; - *c |= (C_u32)(s[3] & 0x3f) << 0; + if (slen > 0) *c = (C_u32)(s[0] & masks[len]) << 18; + if (slen > 1) *c |= (C_u32)(s[1] & 0x3f) << 12; + if (slen > 2) *c |= (C_u32)(s[2] & 0x3f) << 6; + if (slen > 3) *c |= (C_u32)(s[3] & 0x3f) << 0; *c >>= shiftc[len]; /* Accumulate the various error conditions. */ *e = (*c < mins[len]) << 6; // non-canonical encoding *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half? *e |= (*c > 0x10FFFF) << 8; // out of range? - *e |= (s[1] & 0xc0) >> 2; - *e |= (s[2] & 0xc0) >> 4; - *e |= (s[3] ) >> 6; + if (slen > 1) *e |= (s[1] & 0xc0) >> 2; + if (slen > 2) *e |= (s[2] & 0xc0) >> 4; + if (slen > 3) *e |= (s[3] ) >> 6; *e ^= 0x2a; // top two bits of each tail byte correct? *e >>= shifte[len]; @@ -3263,7 +3263,7 @@ static C_char *utf_index1(C_word s, C_word i) return p; } p1 = p; - p = utf8_decode(p, &c, &e); + p = utf8_decode(p, &c, &e, (count-index)); ++index; off += p - p1; } @@ -3289,9 +3289,10 @@ static C_char *utf_index(C_word s, C_word i) C_regparm C_word C_utf_subchar(C_word s, C_word i) { C_char *p = utf_index(s, C_unfix(i)); + C_word len = C_unfix(C_block_item(s, 1)); int e; C_u32 c; - utf8_decode(p, &c, &e); + utf8_decode(p, &c, &e, len); return C_make_character(c); } @@ -3504,7 +3507,7 @@ C_regparm int C_utf_count(C_char *s, int len) int e; C_char *s2; while (len > 0) { - s2 = utf8_decode(s, &c, &e); + s2 = utf8_decode(s, &c, &e, len); len -= (s2 - s); s = s2; i++; @@ -3523,7 +3526,7 @@ C_regparm C_word C_utf_validate(C_word bv, C_word blen, C_word start, C_word end while (len > 0) { if(*s >= 0x80 && *s <= 0xbf) return C_SCHEME_FALSE; if(lengths[*s >> 3] > len) return C_SCHEME_FALSE; - s2 = (unsigned char *)utf8_decode((C_char *)s, &c, &e); + s2 = (unsigned char *)utf8_decode((C_char *)s, &c, &e, len); if(e) return C_SCHEME_FALSE; len -= (s2 - s); s = s2; @@ -3561,7 +3564,8 @@ C_regparm C_word C_utf_decode(C_word bv, C_word pos) { C_u32 c; int e; - utf8_decode(C_c_string(bv) + C_unfix(pos), &c, &e); + C_word bvlen = C_header_size(bv) - 1; + utf8_decode(C_c_string(bv) + C_unfix(pos), &c, &e, bvlen); return C_make_character(c); }