Repository navigation
BasicJsonParser mishandles braces within string values - #52182
Open
zhoubiao188 wants to merge 1 commit into
Open
zhoubiao188 wants to merge 1 commit into
zhoubiao188 wants to merge 1 commit into
Conversation
`BasicJsonParser.tokenize()` tracks the nesting of objects and lists while
it splits the JSON on the commas that are not nested. The tracking of
`'{'`, `'}'`, `'['` and `']'` was applied unconditionally, including when
the character appears within a string literal. An opening brace or bracket
in a string value therefore incremented the nesting count, and the comma
that follows the entry was no longer treated as a separator. The entries
were merged into a single token and silently dropped.
For example, `{"foo":"{","bar":"baz"}` was parsed as a single entry `foo`
with the value `{","bar":"baz` rather than `foo` -> `{` and
`bar` -> `baz`. In the same way `["{","baz"]` produced a single element.
A closing brace within a string had the opposite effect, driving the count
negative and hiding the comma that separates the entries of a sibling
object. `{"a":"}","b":{"c":"d","e":"f"}}` then mapped `b` to `{c=d}` and
turned `e` into an entry of the enclosing object.
This commit only updates the nesting count when the character is not part
of a string literal, which restores the behaviour of the Gson and Jackson
parsers for these inputs. Strings containing commas are already supported
and tested, so braces and brackets within a string must be handled in the
same way.
Signed-off-by: zhoubiao188 <32508238+zhoubiao188@users.noreply.github.com>
This branch has not been deployed
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.
BasicJsonParser.tokenize()tracks the nesting of objects and lists while it splits the JSON on the commas that are not nested, so that a comma inside a string does not separate entries. The tracking of'{','}','['and']'was applied unconditionally, including for characters that appear within a string literal. An opening brace or bracket in a string value therefore incremented the nesting count, and the comma that follows the entry was no longer treated as a separator. The entries were merged into a single token and silently dropped.For example:
{"foo":"{","bar":"baz"}parsed as a single entryfoowith the value{","bar":"baz, instead offoo->{andbar->baz["{","baz"]parsed as a single element{","baz{"foo":"[","bar":"baz"}parsed as a single entryfoowith the value[","bar":"bazA closing brace or bracket within a string has the opposite effect: it drives the nesting count negative, which hides the comma that separates the entries of a sibling object.
{"a":"}","b":{"c":"d","e":"f"}}mappedbto{c=d}and promotedeto an entry of the enclosing object, instead ofa->},b->{c=d, e=f}Strings containing commas are already supported and covered by
stringContainingComma, so braces and brackets within a string need to be handled in the same way. The tokenizer already tracks the in-string state inTracked.VALUE; this commit uses it to only update the nesting count when the character is not part of a string.GsonJsonParserandJacksonJsonParserboth return the expected result for all of the inputs above.The four new tests fail on
mainand pass with the change:To make sure the fix does not trade one set of inputs for another, the two parsers were exhaustively compared with
GsonJsonParserover every combination of the characters{,},[,],,andaplaced in the two string values of{"a":"X","b":"Y"}and["X","Y"]. Of the 3698 inputs that Gson accepts,BasicJsonParsercurrently returns a wrong result for 1548 of them; with this change it returns the result Gson produces for all 3698, and no input that was previously correct changes its result../gradlew :core:spring-boot:checkFormatMain :core:spring-boot:checkFormatTest :core:spring-boot:checkstyleMain :core:spring-boot:checkstyleTest :core:spring-boot:test --tests "org.springframework.boot.json.*"passes.