Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Fixed
-
None
-
None
Description
In big5, a character is either one byte (ASCII) or two bytes: a lead byte followed by a trail byte. The trail byte can be 0x5C, which is also the backslash the connector inserts to escape a quote. So when the connector escapes a big5 value, it must know which bytes are lead bytes: after a lead byte, the following 0x5C belongs to the character and must be copied as is; anywhere else, a 0x5C or a quote must be escaped. lib/misc/charset-mb.js (added for CVE-2026-55855) holds that knowledge for big5, gbk, sjis, cp932 and gb18030.
The connector's big5 table says lead bytes are 0xA1–0xFE. The server says 0xA1–0xF9 (strings/ctype-big5.c, isbig5head), and Connector/C the same (libmariadb/ma_charset.c, valid_big5head). The connector's range came from the Big5 encoding as documented (cp950 / Big5-HKSCS, where 0xFA–0xFE is the user-defined area); the server implements the original 1984 Big5 table, which stops at 0xF9. Verified on the server: SELECT CHAR_LENGTH(_big5 0xF95C) returns 1, _big5 0xFA5C raises ERROR 1300 Invalid big5 character string.
Effect. For a Buffer or stream parameter containing the bytes FA 5C 27 followed by SQL text:
The connector takes FA for a lead byte and 5C for its trail, copies FA 5C unchanged, then escapes the quote: wire bytes FA 5C 5C 27 ….
The server does not consider FA a lead byte. It reads FA alone, then 5C 5C as an escaped backslash, then 27 as a bare quote that ends the string literal. The bytes after it are parsed as SQL.
The same wire bytes with F9 are safe, because both sides agree F9 is a lead byte. Five lead bytes (0xFA–0xFE) behave like this; the other four charsets have ranges that match the server's, and a sweep of every lead byte 0x80–0xFF finds no injecting byte for them.
thanks to fg0x0 for report