From ad5e8fee8d8d24b5ef162ae689a98f71d45c228d Mon Sep 17 00:00:00 2001 From: Colin Vidal Date: Thu, 2 Jul 2026 09:52:09 +0200 Subject: [PATCH] Detect UTF-16 surrogates in `isc_utf8_valid()` UTF-8 standard forbid usage of unicode character between the range of 0xD800..0xDFFF (reserved, and used as UTF-16 surrogates, see RFC 3629). However, `usc_utf8_valid()` was not checking if the encoded unicode character was in this range, which then would accept invalid UTF-8 strings. This is now fixed. --- lib/isc/utf8.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/lib/isc/utf8.c b/lib/isc/utf8.c index 9bc2a74fb9..fb78338421 100644 --- a/lib/isc/utf8.c +++ b/lib/isc/utf8.c @@ -33,9 +33,20 @@ isc_utf8_valid(const unsigned char *buf, size_t len) { REQUIRE(buf != NULL); for (size_t i = 0; i < len; i++) { + /* + * ASCII character range (first row). + */ if (buf[i] <= 0x7f) { continue; } + + /* + * 0x80 -> 1000 0000 + * 0xC0 -> 1100 0000 + * 0xE0 -> 1110 0000 + * + * Is unicode character is encoded using 2 bytes (second row). + */ if ((i + 1) < len && (buf[i] & 0xe0) == 0xc0 && (buf[i + 1] & 0xc0) == 0x80) { @@ -47,6 +58,15 @@ isc_utf8_valid(const unsigned char *buf, size_t len) { } continue; } + + /* + * 0x80 -> 1000 0000 + * 0xC0 -> 1100 0000 + * 0xE0 -> 1110 0000 + * 0xF0 -> 1111 0000 + * + * Is unicode character is encoded within 3 bytes (third row). + */ if ((i + 2) < len && (buf[i] & 0xf0) == 0xe0 && (buf[i + 1] & 0xc0) == 0x80 && (buf[i + 2] & 0xc0) == 0x80) { @@ -57,8 +77,26 @@ isc_utf8_valid(const unsigned char *buf, size_t len) { if (w < 0x0800) { return false; } + + /* + * Unicode range 0xD800..0xDFFF is reserved (UTF16 + * surrogates) + */ + if (w >= 0xD800 && w <= 0xDFFF) { + return false; + } continue; } + + /* + * 0x80 -> 1000 0000 + * 0xC0 -> 1100 0000 + * 0xE0 -> 1110 0000 + * 0xF0 -> 1111 0000 + * 0xF8 -> 1111 1000 + * + * Is unicode character is encoded within 4 bytes (fourth row). + */ if ((i + 3) < len && (buf[i] & 0xf8) == 0xf0 && (buf[i + 1] & 0xc0) == 0x80 && (buf[i + 2] & 0xc0) == 0x80 && (buf[i + 3] & 0xc0) == 0x80)