修复JSONUtil.parse()溢出问题

This commit is contained in:
Looly 2023-09-05 14:32:41 +08:00
parent 9c51a71e20
commit b6944fd18d
4 changed files with 15 additions and 11 deletions

View File

@ -84,7 +84,7 @@ public class JSONParser {
} }
default: default:
tokener.back(); tokener.back();
key = tokener.nextValue().toString(); key = tokener.nextValue(true).toString();
} }
// The key is followed by ':'. // The key is followed by ':'.
@ -94,7 +94,7 @@ public class JSONParser {
throw tokener.syntaxError("Expected a ':' after a key"); throw tokener.syntaxError("Expected a ':' after a key");
} }
jsonObject.set(key, tokener.nextValue(), predicate); jsonObject.set(key, tokener.nextValue(false), predicate);
// Pairs are separated by ','. // Pairs are separated by ','.
@ -136,7 +136,7 @@ public class JSONParser {
jsonArray.addRaw(null, predicate); jsonArray.addRaw(null, predicate);
} else { } else {
x.back(); x.back();
jsonArray.addRaw(x.nextValue(), predicate); jsonArray.addRaw(x.nextValue(false), predicate);
} }
switch (x.nextClean()) { switch (x.nextClean()) {
case CharUtil.COMMA: case CharUtil.COMMA:

View File

@ -345,15 +345,16 @@ public class JSONTokener extends ReaderWrapper {
* @return Boolean, Double, Integer, JSONArray, JSONObject, Long, or String * @return Boolean, Double, Integer, JSONArray, JSONObject, Long, or String
* @throws JSONException 语法错误 * @throws JSONException 语法错误
*/ */
public Object nextValue() throws JSONException { public Object nextValue(final boolean getOnlyStringValue) throws JSONException {
char c = this.nextClean(); char c = this.nextClean();
final String string;
switch (c) { switch (c) {
case '"': case '"':
case '\'': case '\'':
return this.nextString(c); return this.nextString(c);
case '{': case '{':
if(getOnlyStringValue){
throw this.syntaxError("String value must not begin with '{'");
}
this.back(); this.back();
try { try {
return new JSONObject(this, this.config); return new JSONObject(this, this.config);
@ -361,6 +362,9 @@ public class JSONTokener extends ReaderWrapper {
throw new JSONException("JSONObject depth too large to process.", e); throw new JSONException("JSONObject depth too large to process.", e);
} }
case '[': case '[':
if(getOnlyStringValue){
throw this.syntaxError("String value must not begin with '['");
}
this.back(); this.back();
try { try {
return new JSONArray(this, this.config); return new JSONArray(this, this.config);
@ -382,11 +386,11 @@ public class JSONTokener extends ReaderWrapper {
} }
this.back(); this.back();
string = sb.toString().trim(); final String valueString = sb.toString().trim();
if (0 == string.length()) { if (valueString.isEmpty()) {
throw this.syntaxError("Missing value"); throw this.syntaxError("Missing value");
} }
return InternalJSONUtil.stringToValue(string); return getOnlyStringValue ? valueString : InternalJSONUtil.stringToValue(valueString);
} }
/** /**

View File

@ -154,7 +154,7 @@ public class JSONConverter implements Converter {
return new JSONObject(jsonStr, config); return new JSONObject(jsonStr, config);
default: default:
// RFC8259JSON字符串值number, boolean, or null // RFC8259JSON字符串值number, boolean, or null
final Object value = new JSONTokener(jsonStr, config).nextValue(); final Object value = new JSONTokener(jsonStr, config).nextValue(false);
if(ObjUtil.equals(value, jsonStr)){ if(ObjUtil.equals(value, jsonStr)){
// 原值返回意味着非正常数字Boolean或null // 原值返回意味着非正常数字Boolean或null
throw new JSONException("Unsupported JSON String: {}", jsonStr); throw new JSONException("Unsupported JSON String: {}", jsonStr);

View File

@ -7,7 +7,7 @@ public class Issue3289Test {
@Test @Test
void parseTest() { void parseTest() {
Assertions.assertThrows(JSONException.class, () -> { Assertions.assertThrows(JSONException.class, () -> {
final String s = "{\"G\":00,[,,[0E5,6E9,6E5,6E9,6E5,6E9,6E5,6E9,6E9,6E5,true,6E5,6E9,6E5,6E9,6956,EE,5E9,6E5,RE,6E9,6E9,6E5,6E9,6E5,6E9,6E5,6E9,6E5,6E962756779,4141697],]}"; String s = "{\"G\":00,[6E962756779]}";
JSONUtil.parse(s); JSONUtil.parse(s);
}); });
} }