Skip to content

Commit 8746735

Browse files
authored
Merge pull request #1074 from XIAYM-gh/master
Fix strict mode failure when JSONTokener.next() and back() are called before parsing
2 parents 4f859fd + a25f83a commit 8746735

5 files changed

Lines changed: 141 additions & 9 deletions

File tree

src/main/java/org/json/JSONArray.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ public JSONArray() {
8080
* @param x
8181
* A JSONTokener
8282
* @throws JSONException
83-
* If there is a syntax error.
83+
* If there is a syntax error.
8484
*/
8585
public JSONArray(JSONTokener x) throws JSONException {
8686
this(x, x.getJsonParserConfiguration());
@@ -94,9 +94,21 @@ public JSONArray(JSONTokener x) throws JSONException {
9494
* @throws JSONException If a syntax error occurs during the construction of the JSONArray.
9595
*/
9696
public JSONArray(JSONTokener x, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
97+
this(x, jsonParserConfiguration, true);
98+
}
99+
100+
/**
101+
* Constructs a JSONArray from a JSONTokener and a JSONParserConfiguration, for internal use. <br>
102+
* Never call this instead of using withStrictMode(boolean).
103+
*
104+
* @param x A JSONTokener instance from which the JSONArray is constructed.
105+
* @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser.
106+
* @param isInitial A boolean that determines whether this array is the root.
107+
* @throws JSONException If a syntax error occurs during the construction of the JSONArray.
108+
*/
109+
JSONArray(JSONTokener x, JSONParserConfiguration jsonParserConfiguration, boolean isInitial) throws JSONException {
97110
this();
98111

99-
boolean isInitial = x.getPrevious() == 0;
100112
if (x.nextClean() != '[') {
101113
throw x.syntaxError("A JSONArray text must start with '['");
102114
}

src/main/java/org/json/JSONObject.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,8 @@ public JSONObject(JSONObject jo, String ... names) {
195195
* @param x
196196
* A JSONTokener object containing the source string.
197197
* @throws JSONException
198-
* If there is a syntax error in the source string or a
199-
* duplicated key.
198+
* If there is a syntax error in the source string or a
199+
* duplicated key.
200200
*/
201201
public JSONObject(JSONTokener x) throws JSONException {
202202
this(x, x.getJsonParserConfiguration());
@@ -210,12 +210,29 @@ public JSONObject(JSONTokener x) throws JSONException {
210210
* @param jsonParserConfiguration
211211
* Variable to pass parser custom configuration for json parsing.
212212
* @throws JSONException
213-
* If there is a syntax error in the source string or a
214-
* duplicated key.
213+
* If there is a syntax error in the source string or a
214+
* duplicated key.
215215
*/
216216
public JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
217+
this(x, jsonParserConfiguration, true);
218+
}
219+
220+
/**
221+
* Construct a JSONObject from a JSONTokener with custom json parse configurations, for internal use. <br>
222+
* Never call this instead of using withStrictMode(boolean).
223+
*
224+
* @param x
225+
* A JSONTokener object containing the source string.
226+
* @param jsonParserConfiguration
227+
* Variable to pass parser custom configuration for json parsing.
228+
* @param isInitial
229+
* A boolean that determines whether this object is the root.
230+
* @throws JSONException
231+
* If there is a syntax error in the source string or a
232+
* duplicated key.
233+
*/
234+
JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration, boolean isInitial) throws JSONException {
217235
this();
218-
boolean isInitial = x.getPrevious() == 0;
219236

220237
if (x.nextClean() != '{') {
221238
throw x.syntaxError("A JSONObject text must begin with '{'");

src/main/java/org/json/JSONTokener.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -458,14 +458,14 @@ public Object nextValue() throws JSONException {
458458
case '{':
459459
this.back();
460460
try {
461-
return new JSONObject(this, jsonParserConfiguration);
461+
return new JSONObject(this, jsonParserConfiguration, false);
462462
} catch (StackOverflowError e) {
463463
throw new JSONException("JSON Array or Object depth too large to process.", e);
464464
}
465465
case '[':
466466
this.back();
467467
try {
468-
return new JSONArray(this, jsonParserConfiguration);
468+
return new JSONArray(this, jsonParserConfiguration, false);
469469
} catch (StackOverflowError e) {
470470
throw new JSONException("JSON Array or Object depth too large to process.", e);
471471
}

src/test/java/org/json/junit/JSONArrayTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,4 +1566,56 @@ public void TestLenientCommas() {
15661566
"[1,null,3]", jsonArray.toString());
15671567
}
15681568
}
1569+
1570+
@Test
1571+
public void strictModeShouldCheckTrailingCharactersAfterNextAndBack() {
1572+
JSONParserConfiguration strict =
1573+
new JSONParserConfiguration().withStrictMode();
1574+
1575+
JSONTokener tok = new JSONTokener("[]xxx");
1576+
tok.next();
1577+
tok.back();
1578+
1579+
JSONException exception = assertThrows(
1580+
JSONException.class,
1581+
() -> new JSONArray(tok, strict));
1582+
1583+
assertTrue(exception.getMessage().contains(
1584+
"Unparsed characters found at end of input text"));
1585+
}
1586+
1587+
@Test
1588+
public void strictModeShouldCheckTrailingCharactersAfterConsumedWhitespace() {
1589+
JSONParserConfiguration strict =
1590+
new JSONParserConfiguration().withStrictMode();
1591+
1592+
JSONTokener tok = new JSONTokener(" []xxx");
1593+
tok.next();
1594+
tok.next();
1595+
tok.back();
1596+
1597+
JSONException exception = assertThrows(
1598+
JSONException.class,
1599+
() -> new JSONArray(tok, strict));
1600+
1601+
assertTrue(exception.getMessage().contains(
1602+
"Unparsed characters found at end of input text"));
1603+
}
1604+
1605+
@Test
1606+
public void strictModeShouldCheckTrailingCharactersAfterNextCleanAndBack() {
1607+
JSONParserConfiguration strict =
1608+
new JSONParserConfiguration().withStrictMode();
1609+
1610+
JSONTokener tok = new JSONTokener(" []xxx");
1611+
tok.nextClean();
1612+
tok.back();
1613+
1614+
JSONException exception = assertThrows(
1615+
JSONException.class,
1616+
() -> new JSONArray(tok, strict));
1617+
1618+
assertTrue(exception.getMessage().contains(
1619+
"Unparsed characters found at end of input text"));
1620+
}
15691621
}

src/test/java/org/json/junit/JSONObjectTest.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4337,4 +4337,55 @@ public void testStringToNumberInvalidFormats() {
43374337
}
43384338
}
43394339

4340+
@Test
4341+
public void strictModeShouldCheckTrailingCharactersAfterNextAndBack() {
4342+
JSONParserConfiguration strict =
4343+
new JSONParserConfiguration().withStrictMode();
4344+
4345+
JSONTokener tok = new JSONTokener("{}xxx");
4346+
tok.next();
4347+
tok.back();
4348+
4349+
JSONException exception = assertThrows(
4350+
JSONException.class,
4351+
() -> new JSONObject(tok, strict));
4352+
4353+
assertTrue(exception.getMessage().contains(
4354+
"Unparsed characters found at end of input text"));
4355+
}
4356+
4357+
@Test
4358+
public void strictModeShouldCheckTrailingCharactersAfterConsumedWhitespace() {
4359+
JSONParserConfiguration strict =
4360+
new JSONParserConfiguration().withStrictMode();
4361+
4362+
JSONTokener tok = new JSONTokener(" {}xxx");
4363+
tok.next();
4364+
tok.next();
4365+
tok.back();
4366+
4367+
JSONException exception = assertThrows(
4368+
JSONException.class,
4369+
() -> new JSONObject(tok, strict));
4370+
4371+
assertTrue(exception.getMessage().contains(
4372+
"Unparsed characters found at end of input text"));
4373+
}
4374+
4375+
@Test
4376+
public void strictModeShouldCheckTrailingCharactersAfterNextCleanAndBack() {
4377+
JSONParserConfiguration strict =
4378+
new JSONParserConfiguration().withStrictMode();
4379+
4380+
JSONTokener tok = new JSONTokener(" {}xxx");
4381+
tok.nextClean();
4382+
tok.back();
4383+
4384+
JSONException exception = assertThrows(
4385+
JSONException.class,
4386+
() -> new JSONObject(tok, strict));
4387+
4388+
assertTrue(exception.getMessage().contains(
4389+
"Unparsed characters found at end of input text"));
4390+
}
43404391
}

0 commit comments

Comments
 (0)