fix(read): stop misclassifying UTF-8 text files as binary - #79641
fix(read): stop misclassifying UTF-8 text files as binary#79641enedelko wants to merge 1 commit into
Conversation
read_file sampled the first 1000 bytes with `head -c 1000`, which can cut mid-way through a multi-byte UTF-8 character. The truncated byte sequence decoded to U+FFFD (replacement char), and the binary detector — correctly treating U+FFFD as mojibake — flagged the file as binary and refused to read it. Legitimate Cyrillic/UTF-8 text files were blocked roughly half the time depending on where byte 1000 landed. Sample with python instead: read the first 1000 bytes, decode with errors='ignore' so a split multi-byte char is dropped instead of becoming U+FFFD. Real binary files are still caught by the >30% non-printable ratio check in _is_likely_binary.
|
This was generated by AI during triage. Summary: Problems:
Solution: Checked against |
|
独立复现 + 修正版实现,见 #80261。 复现(中文 UTF-8 markdown,Windows):文件前 1000 字节恰好切在 3 字节中文字符中间时(例如 998 个 ASCII 字节 + 一个中文), 关于 修正版方案(#80261):采样时把窗口扩展到下一个 UTF-8 字符边界(跳过延续字节),样本永远是完整字符;真实损坏字节仍产生 U+FFFD 并被捕获。另修复了原实现里 |
|
Closing — superseded by #81961, which fixed this bug class (1000-byte sample cutting a multibyte char → binary false positive) at the byte layer across read_file, patch, and search_files, with regression tests for truncated-CJK/BOM/UTF-16/NUL cases. ~24 PRs raced on this one; earliest diagnosis credit to @webtecnica (#76924), merged implementation from @ayushnangia (#80440). Thanks for jumping on it. |
Problem
read_filesamples the first 1000 bytes withhead -c 1000, which cuts the file at an arbitrary byte boundary. When byte 1000 lands mid-way through a multi-byte UTF-8 character (2 bytes for Cyrillic, 3-4 for other scripts/emoji), the truncated tail decodes to U+FFFD (replacement char).The binary detector in
_is_likely_binarytreats U+FFFD as mojibake (correctly, for real corruption) and flags the file as binary, refusing to read it. Result: legitimate UTF-8 text files (e.g. Russian markdown) are randomly blocked roughly half the time.Fix
Read the sample with python instead of
head -c 1000: same first 1000 bytes, decoded witherrors="ignore"so a split multi-byte char is dropped instead of becoming U+FFFD. Real binary files are still caught by the non-printable ratio check in_is_likely_binary. Both call sites patched;sysimport added.