next16: report invalid_utf16 for a lone trail surrogate at the end of a range - #147
Merged
Merged
Conversation
… a range
validate_next16 returns NOT_ENOUGH_ROOM whenever the second word is missing,
without first asking whether the first word is a lead surrogate. A trail
surrogate is invalid UTF-16 on its own, so no second word can rescue it:
{0xdc00, 0x0041} -> invalid_utf16 (test_next16, trail_first)
{0xdc00} -> not_enough_room
Move the is_lead_surrogate test above the end-of-range test so the reported
error depends on the first word rather than on what happens to follow it.
NOT_ENOUGH_ROOM is still returned for a lead surrogate at the end of the
range, which is a genuinely truncated sequence.
Owner
|
Thanks! |
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.
Problem
utf8::next16reports a different error for the same invalid first word depending on what follows it:0xdc00is a trail surrogate. It is invalid UTF-16 no matter how many words come after it, so no second word can make it valid and "not enough room" is not the right diagnosis.The cause is statement order in
internal::validate_next16(source/utf8/core.h:437-441onmain): theit == endtest runs before the code decides whetherfirst_wordis a lead surrogate, so the lone-trail case never reaches theINVALID_LEADbranch.This is the one cell your own test table does not cover. 87ca49f ("next16 properly reports errors", fixing #144) wired up the mapping in
checked.h:177-178and added a table totests/test_checked_api.h:0xd800not_enough_room0xd8000x0041invalid_utf160xdc000x0041invalid_utf160xdc00The fourth row is the one that is still wrong.
API_REFERENCE.md:209scopesnot_enough_roomto "ifitgets equal toendduring the extraction of a code point", andAPI_REFERENCE.md:225says an invalid UTF-16 sequence throwsinvalid_utf16. With a lone trail surrogate there is no code point being extracted, so the second sentence is the applicable one.utf16to8agrees already:checked.h:247-248throwsinvalid_utf16for a lone trail surrogate regardless of position.Fix
Move the
is_lead_surrogatetest above the end-of-range test. Oneelse ifbranch, no new logic. A lead surrogate at the end of a range still returnsNOT_ENOUGH_ROOM, since that one really is truncated.Verification
g++ 13.3.0, linux/amd64, base 30e55c2, built with the flags from
tests/CMakeLists.txt(-Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion, per-target-std).negative12,cpp1110,cpp179,cpp208,apitests35 (34 before, +1 new),noexceptionstests15. No new warnings.core.hreverted tomainand the new test in place,apitestsfails exactly one test,CheckedAPITests.test_next16_lone_trail_surrogate.it == end->INVALID_LEAD, so a lead surrogate at the end is reported as invalid too) fails exactly one test, and it is the pre-existingCheckedAPITests.test_next16. The two failure sets are disjoint, so the boundary is pinned from both sides by the repo's own table plus the new case.The new test only adds the missing row; I deliberately did not duplicate the three rows
test_next16already covers.Disclosure: I used an AI assistant while preparing this change. I read, built, ran and verified everything above myself. If you would rather keep the current behaviour and simply document it, I am happy to close this.