Refuse to open non-UTF-8 files instead of destroying them - #61
Merged
Conversation
readFile 이 무조건 fs.readFile(abs, "utf8") 이었다. UTF-8 이 아닌 파일은 디코딩에서 U+FFFD 로 바뀌고, 그 상태로 저장하면 원본이 사라진다. 되돌릴 방법이 없다. 재현했다. UTF-16 파일은 열고 Ctrl+S 만 눌러도 16바이트가 20바이트가 됐다. CP949 로 저장된 한글 파일은 `// �ȳ� ����` 로 뜨고, 한 글자만 고쳐 저장하면 파일 전체가 사라진다. 윈도우에서 아주 흔한 인코딩이다. electron/encoding.cjs 에 순수 판정을 두고(BOM·NUL·UTF-8 왕복 비교), readFile 이 아니라고 판단하면 열지 않고 이유를 돌려준다. 렌더러는 그 코드를 4개국어 안내 문구로 바꿔 편집기 자리에 띄운다 — 왜 안 열리는지 말해 주지 않으면 그냥 고장 난 편집기로 보인다. 다른 인코딩을 읽어 주는 것은 기능이고, 조용히 부수지 않는 것은 그 전에 지켜야 할 일이다. 실제 앱 검증 7/7 (고치기 전 2/5), 단위 954개 통과.
This was referenced Aug 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
schutz:readFilewas unconditionallyfs.readFile(abs, "utf8"). Anything that is not UTF-8 comes back as U+FFFD replacement characters, and saving writes those replacements to disk. The original bytes are gone, with no undo.Reproduced in the real app:
Ctrl+Salone: 16 bytes → 20 bytes// �ȳ� ����; one edit + save destroys the whole fileThe fix
electron/encoding.cjsis a pure decision — BOM check, NUL check, UTF-8 round-trip comparison — returningnullwhen the bytes are safe, or why they are not (utf16le/utf16be/binary/not-utf8).readFilenow reads bytes, asks, and refuses to open the file instead of handing back a mangled string.The renderer maps the code to a translated message (4 languages) in the editor's error surface. Refusing without saying why just looks like a broken editor.
Reading other encodings is a feature; not silently destroying files is a prerequisite. This does the prerequisite.
Verification
detect/errorFor/kindOf; 954 total passing.npm run typecheckclean.main.cjsline endings unchanged (1873 CRLF / 0 LF).