Skip to content

Commit 14f7127

Browse files
authored
Merge pull request stleary#888 from rikkarth/fix/887
fix(stleary#887): complete strictMode for JSONArray
2 parents 054786e + a8ab79e commit 14f7127

12 files changed

+502
-188
lines changed

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

Lines changed: 75 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -96,53 +96,83 @@ public JSONArray(JSONTokener x) throws JSONException {
9696
*/
9797
public JSONArray(JSONTokener x, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
9898
this();
99-
if (x.nextClean() != '[') {
99+
char nextChar = x.nextClean();
100+
101+
// check first character, if not '[' throw JSONException
102+
if (nextChar != '[') {
100103
throw x.syntaxError("A JSONArray text must start with '['");
101104
}
102105

103-
char nextChar = x.nextClean();
104-
if (nextChar == 0) {
105-
// array is unclosed. No ']' found, instead EOF
106-
throw x.syntaxError("Expected a ',' or ']'");
107-
}
108-
if (nextChar != ']') {
109-
x.back();
110-
for (;;) {
111-
if (x.nextClean() == ',') {
112-
x.back();
113-
this.myArrayList.add(JSONObject.NULL);
114-
} else {
115-
x.back();
116-
this.myArrayList.add(x.nextValue(jsonParserConfiguration));
106+
parseTokener(x, jsonParserConfiguration); // runs recursively
107+
108+
}
109+
110+
private void parseTokener(JSONTokener x, JSONParserConfiguration jsonParserConfiguration) {
111+
boolean strictMode = jsonParserConfiguration.isStrictMode();
112+
113+
char cursor = x.nextClean();
114+
115+
switch (cursor) {
116+
case 0:
117+
throwErrorIfEoF(x);
118+
break;
119+
case ',':
120+
cursor = x.nextClean();
121+
122+
throwErrorIfEoF(x);
123+
124+
if(strictMode && cursor == ']'){
125+
throw x.syntaxError(getInvalidCharErrorMsg(cursor));
117126
}
118-
switch (x.nextClean()) {
119-
case 0:
120-
// array is unclosed. No ']' found, instead EOF
121-
throw x.syntaxError("Expected a ',' or ']'");
122-
case ',':
123-
nextChar = x.nextClean();
124-
if (nextChar == 0) {
125-
// array is unclosed. No ']' found, instead EOF
126-
throw x.syntaxError("Expected a ',' or ']'");
127-
}
128-
if (nextChar == ']') {
129-
return;
130-
}
131-
x.back();
127+
128+
if (cursor == ']') {
129+
break;
130+
}
131+
132+
x.back();
133+
134+
parseTokener(x, jsonParserConfiguration);
135+
break;
136+
case ']':
137+
if (strictMode) {
138+
cursor = x.nextClean();
139+
boolean isEoF = x.end();
140+
141+
if (isEoF) {
132142
break;
133-
case ']':
134-
if (jsonParserConfiguration.isStrictMode()) {
135-
nextChar = x.nextClean();
136-
if (nextChar != 0) {
137-
throw x.syntaxError("invalid character found after end of array: " + nextChar);
138-
}
139-
}
140-
141-
return;
142-
default:
143-
throw x.syntaxError("Expected a ',' or ']'");
143+
}
144+
145+
if (x.getArrayLevel() == 0) {
146+
throw x.syntaxError(getInvalidCharErrorMsg(cursor));
147+
}
148+
149+
x.back();
144150
}
145-
}
151+
break;
152+
default:
153+
x.back();
154+
boolean currentCharIsQuote = x.getPrevious() == '"';
155+
boolean quoteIsNotNextToValidChar = x.getPreviousChar() != ',' && x.getPreviousChar() != '[';
156+
157+
if (strictMode && currentCharIsQuote && quoteIsNotNextToValidChar) {
158+
throw x.syntaxError(getInvalidCharErrorMsg(cursor));
159+
}
160+
161+
this.myArrayList.add(x.nextValue(jsonParserConfiguration));
162+
parseTokener(x, jsonParserConfiguration);
163+
}
164+
}
165+
166+
/**
167+
* Throws JSONException if JSONTokener has reached end of file, usually when array is unclosed. No ']' found,
168+
* instead EoF.
169+
*
170+
* @param x the JSONTokener being evaluated.
171+
* @throws JSONException if JSONTokener has reached end of file.
172+
*/
173+
private void throwErrorIfEoF(JSONTokener x) {
174+
if (x.end()) {
175+
throw x.syntaxError(String.format("Expected a ',' or ']' but instead found '%s'", x.getPrevious()));
146176
}
147177
}
148178

@@ -1932,6 +1962,7 @@ private void addAll(Object array, boolean wrap) throws JSONException {
19321962
private void addAll(Object array, boolean wrap, int recursionDepth) {
19331963
addAll(array, wrap, recursionDepth, new JSONParserConfiguration());
19341964
}
1965+
19351966
/**
19361967
* Add an array's elements to the JSONArray.
19371968
*`
@@ -1978,7 +2009,6 @@ private void addAll(Object array, boolean wrap, int recursionDepth, JSONParserCo
19782009
"JSONArray initial value should be a string or collection or array.");
19792010
}
19802011
}
1981-
19822012
/**
19832013
* Create a new JSONException in a common format for incorrect conversions.
19842014
* @param idx index of the item
@@ -2007,4 +2037,7 @@ private static JSONException wrongValueFormatException(
20072037
, cause);
20082038
}
20092039

2040+
private static String getInvalidCharErrorMsg(char cursor) {
2041+
return String.format("invalid character '%s' found after end of array", cursor);
2042+
}
20102043
}

0 commit comments

Comments
 (0)