avoid sign extension in char_traits<signed char>::to_int_type - #5336
Open
Angadi56 wants to merge 1 commit into
Open
avoid sign extension in char_traits<signed char>::to_int_type#5336Angadi56 wants to merge 1 commit into
Angadi56 wants to merge 1 commit into
Conversation
Signed-off-by: Angadi Yashaswini <angadi@digiscrypt.com>
This comment was marked as outdated.
This comment was marked as outdated.
nlohmann
requested changes
Jul 30, 2026
nlohmann
left a comment
Owner
There was a problem hiding this comment.
Looks good, but AppVeyor is complaining about the newly added test code:
unit-type_traits.cpp(69,70): warning C4309: 'static_cast': truncation of constant value
unit-deserialization.cpp(442,447): warning C4309: 'static_cast': truncation of constant value
These are the static_cast<signed char>(0x80), 0xFF, 0xC3, 0xA9 literals - none of those fit in signed char's range (-128..127), so MSVC flags the constant narrowing as an error even through an explicit cast.
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.
char_traitsis specialized here forunsigned char,signed charandstd::byteso that byte containers can be handed to the parser, and each specialization widens a character into a 64-bitint_typewhoseeof()is all-ones. Thesigned charspecialization casts the character straight toint_type, and since every byte above 0x7F is negative in that type, the conversion sign-extends: 0xFF becomes 0xFFFFFFFFFFFFFFFF, which is exactlyeof(). So for an input whose element type issigned char, a 0xFF byte is read as end of input and whatever follows it is dropped without an error, which means a document can carry trailing data past astrictcheck:from_cboron01 FF 41 42 43returns1instead of raisingparse_error.110, andparseontruefollowed by 0xFF behaves the same way. Every other byte above 0x7F picks up the same high bits and stops matching its case label, so CBOR0xF5is reported as an invalid byte and a plain UTF-8éis rejected as ill-formed. I noticed it while lining the three specializations up against each other, since theunsigned charone cannot sign-extend and thestd::byteone deliberately goes throughstd::to_integer<unsigned char>, leavingsigned charas the only one that widens a negative value. Casting throughunsigned charfirst gives all three the same 0..255 range, and becauseto_char_typemaps the value back with a single cast the round trip is unchanged for every byte.make amalgamate.