-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Fixes corner case where strict mode isn't working when JSONTokener's next() and back() are called first #1074
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -195,8 +195,8 @@ public JSONObject(JSONObject jo, String ... names) { | |
| * @param x | ||
| * A JSONTokener object containing the source string. | ||
| * @throws JSONException | ||
| * If there is a syntax error in the source string or a | ||
| * duplicated key. | ||
| * If there is a syntax error in the source string or a | ||
| * duplicated key. | ||
| */ | ||
| public JSONObject(JSONTokener x) throws JSONException { | ||
| this(x, x.getJsonParserConfiguration()); | ||
|
|
@@ -210,12 +210,29 @@ public JSONObject(JSONTokener x) throws JSONException { | |
| * @param jsonParserConfiguration | ||
| * Variable to pass parser custom configuration for json parsing. | ||
| * @throws JSONException | ||
| * If there is a syntax error in the source string or a | ||
| * duplicated key. | ||
| * If there is a syntax error in the source string or a | ||
| * duplicated key. | ||
| */ | ||
| public JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration) throws JSONException { | ||
| this(x, jsonParserConfiguration, x.isAtStart()); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please replace |
||
| } | ||
|
|
||
| /** | ||
| * Construct a JSONObject from a JSONTokener with custom json parse configurations, for internal use. <br> | ||
| * Never call this instead of using withStrictMode(boolean). | ||
| * | ||
| * @param x | ||
| * A JSONTokener object containing the source string. | ||
| * @param jsonParserConfiguration | ||
| * Variable to pass parser custom configuration for json parsing. | ||
| * @param isInitial | ||
| * A boolean that determines whether this object is the root. | ||
| * @throws JSONException | ||
| * If there is a syntax error in the source string or a | ||
| * duplicated key. | ||
| */ | ||
| JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration, boolean isInitial) throws JSONException { | ||
| this(); | ||
| boolean isInitial = x.getPrevious() == 0; | ||
|
|
||
| if (x.nextClean() != '{') { | ||
| throw x.syntaxError("A JSONObject text must begin with '{'"); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,6 +31,8 @@ public class JSONTokener { | |
| private boolean usePrevious; | ||
| /** the number of characters read in the previous line. */ | ||
| private long characterPreviousLine; | ||
| /** number of non-whitespace characters read from the source. */ | ||
| private long contentCharCount; | ||
|
|
||
| // access to this object is required for strict mode checking | ||
| private JSONParserConfiguration jsonParserConfiguration; | ||
|
|
@@ -60,6 +62,7 @@ public JSONTokener(Reader reader, JSONParserConfiguration jsonParserConfiguratio | |
| this.usePrevious = false; | ||
| this.previous = 0; | ||
| this.index = 0; | ||
| this.contentCharCount = 0; | ||
| this.character = 1; | ||
| this.characterPreviousLine = 0; | ||
| this.line = 1; | ||
|
|
@@ -120,6 +123,17 @@ public void setJsonParserConfiguration(JSONParserConfiguration jsonParserConfigu | |
| this.jsonParserConfiguration = jsonParserConfiguration; | ||
| } | ||
|
|
||
| /** | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please remove this method, it is not needed. Sorry, thought you would reason this out based on previous comments. |
||
| * Returns whether the tokener is positioned at the beginning, | ||
| * i.e. only whitespace characters (or no characters at all) have been read so far. | ||
| * Consuming and backing up over the first characters does not change the result. | ||
| * | ||
| * @return true if no non-whitespace character has been read | ||
| */ | ||
| protected boolean isAtStart() { | ||
| return this.contentCharCount == 0; | ||
| } | ||
|
|
||
| /** | ||
| * Back up one character. This provides a sort of lookahead capability, | ||
| * so that you can test for a digit or letter before attempting to parse | ||
|
|
@@ -131,6 +145,9 @@ public void back() throws JSONException { | |
| if (this.usePrevious || this.index <= 0) { | ||
| throw new JSONException("Stepping back two steps is not supported"); | ||
| } | ||
| if (this.previous > ' ') { | ||
| this.contentCharCount--; | ||
| } | ||
| this.decrementIndexes(); | ||
| this.usePrevious = true; | ||
| this.eof = false; | ||
|
|
@@ -231,6 +248,9 @@ public char next() throws JSONException { | |
| return 0; | ||
| } | ||
| this.incrementIndexes(c); | ||
| if (c > ' ') { | ||
| this.contentCharCount++; | ||
| } | ||
| this.previous = (char) c; | ||
| return this.previous; | ||
| } | ||
|
|
@@ -458,14 +478,14 @@ public Object nextValue() throws JSONException { | |
| case '{': | ||
| this.back(); | ||
| try { | ||
| return new JSONObject(this, jsonParserConfiguration); | ||
| return new JSONObject(this, jsonParserConfiguration, false); | ||
| } catch (StackOverflowError e) { | ||
| throw new JSONException("JSON Array or Object depth too large to process.", e); | ||
| } | ||
| case '[': | ||
| this.back(); | ||
| try { | ||
| return new JSONArray(this, jsonParserConfiguration); | ||
| return new JSONArray(this, jsonParserConfiguration, false); | ||
| } catch (StackOverflowError e) { | ||
| throw new JSONException("JSON Array or Object depth too large to process.", e); | ||
| } | ||
|
|
@@ -549,6 +569,7 @@ public char skipTo(char to) throws JSONException { | |
| long startIndex = this.index; | ||
| long startCharacter = this.character; | ||
| long startLine = this.line; | ||
| long startContentCharCount = this.contentCharCount; | ||
| this.reader.mark(1000000); | ||
| do { | ||
| c = this.next(); | ||
|
|
@@ -560,6 +581,7 @@ public char skipTo(char to) throws JSONException { | |
| this.index = startIndex; | ||
| this.character = startCharacter; | ||
| this.line = startLine; | ||
| this.contentCharCount = startContentCharCount; | ||
| return 0; | ||
| } | ||
| } while (c != to); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please replace
x.isAtStart()withtrue