Repository navigation
Return OutputFull when replaying non-BOM bytes into a short buffer - #149
Merged
hsivonen merged 1 commit intoOct 30, 2026
Merged
Conversation
When a sniffing decoder has seen the first byte or two of a potential BOM at the end of one buffer and the next buffer shows that they aren't a BOM, the held bytes are decoded through the real decoder into the next call's `dst`. If that `dst` is too short for their output, the decoder panicked with "Output buffer must have been too small." That happens with a four-byte UTF-8 buffer (the documented minimum) and any encoding where EF and BB decode to more than four bytes together: x-user-defined, ISO-2022-JP, IBM866, windows-874, and the other single-byte encodings that map them outside Latin-1. Instead, return OutputFull and set the life cycle so that the next call replays the bytes that weren't decoded: one held byte goes back to its Seen*First state, EF BB goes back to SeenUtf8Second, and only BB left goes to ConvertingWithPendingBB.
Owner
|
Thank you! |
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.
A decoder made with
new_decoder()panics when the first bytes of a potential BOM arrive at the end of one buffer, turn out not to be a BOM, and the next call's output buffer is too short for them. A four-byte buffer is enough to trigger it, and four bytes is the documented minimum for UTF-8:decode_to_utf_after_one_potential_bom_byteanddecode_to_utf_after_two_potential_bom_bytesdecode the held bytes intodstand treatOutputFullas unreachable. That's wrong whenever EF and BB decode to more than four UTF-8 bytes together. Going through every encoding, held prefix and next buffer, I found 704 panicking cases, all with EF BB held and a 4- or 5-bytedst:The same happens through
decode_to_strand with the_without_replacementvariants.With this change, both functions return
OutputFulland set the life cycle so that the next call replays what wasn't decoded:Seen*Firststate;SeenUtf8Second;ConvertingWithPendingBB, which theMalformedpath already uses for that case.out_read/first_readstay 0, because none of the held bytes came from the currentsrc.To check the resumed state, I ran every encoding, held prefix (EF, EF BB, FE, FF), seven next buffers and every output size from the minimum to 8, through
decode_to_utf8,decode_to_utf8_without_replacementanddecode_to_utf16, retrying afterOutputFull. All 19,040 runs give exactly the spec's decode result and final encoding.The new test
test_short_buffer_after_non_bom_bytescovers IBM866, x-user-defined and ISO-2022-JP with every split of the input and buffers of 4–7 bytes, and compares the joined output. It panics without the change.cargo testpasses on stable, 1.88,--no-default-features,std,simd-accel(nightly), and thefast-legacy-encode/less-slow-*features.cargo fmt --checkpasses too.I found this by fuzzing the streaming decoders against a transcription of the Encoding Standard, with BOM sniffing, random chunking and small output buffers. The test is dedicated to the public domain like the rest of the test module.