From da2e8332395021b3c3b5636a8003377b8e61eaa0 Mon Sep 17 00:00:00 2001 From: ZhangJian He Date: Fri, 7 Jul 2023 23:48:00 +0800 Subject: [PATCH 1/3] add flag to drop the limit of json depth --- .../net/minidev/json/parser/JSONParser.java | 9 ++++++- .../minidev/json/parser/JSONParserBase.java | 7 +++-- .../net/minidev/json/test/TestOverflow.java | 26 +++++++++++++++++-- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java index 4342751d..482eac04 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java @@ -93,6 +93,13 @@ public class JSONParser { * @since 2.4 */ public final static int BIG_DIGIT_UNRESTRICTED = 2048; + + /** + * If limit the max depth of json size + * + * @since 2.5 + */ + public static final int FINITE_JSON_DEPTH = 4096; /** @@ -132,7 +139,7 @@ public class JSONParser { /* * internal fields */ - private int mode; + private final int mode; private JSONParserInputStream pBinStream; private JSONParserByteArray pBytes; diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java index 87a9329a..acff3506 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java @@ -92,6 +92,8 @@ abstract class JSONParserBase { protected final boolean reject127; protected final boolean unrestictBigDigit; + protected final boolean finiteJsonDepth; + public JSONParserBase(int permissiveMode) { this.acceptNaN = (permissiveMode & JSONParser.ACCEPT_NAN) > 0; this.acceptNonQuote = (permissiveMode & JSONParser.ACCEPT_NON_QUOTE) > 0; @@ -107,6 +109,7 @@ public JSONParserBase(int permissiveMode) { this.checkTaillingSpace = (permissiveMode & JSONParser.ACCEPT_TAILLING_SPACE) == 0; this.reject127 = (permissiveMode & JSONParser.REJECT_127_CHAR) > 0; this.unrestictBigDigit = (permissiveMode & JSONParser.BIG_DIGIT_UNRESTRICTED) > 0; + this.finiteJsonDepth = (permissiveMode & JSONParser.FINITE_JSON_DEPTH) > 0; } public void checkControleChar() throws ParseException { @@ -296,7 +299,7 @@ protected Number parseNumber(String s) throws ParseException { protected T readArray(JsonReaderI mapper) throws ParseException, IOException { if (c != '[') throw new RuntimeException("Internal Error"); - if (++this.depth > MAX_DEPTH) { + if (finiteJsonDepth && ++this.depth > MAX_DEPTH) { throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c); } Object current = mapper.createArray(); @@ -553,7 +556,7 @@ protected T readObject(JsonReaderI mapper) throws ParseException, IOExcep // if (c != '{') throw new RuntimeException("Internal Error"); - if (++this.depth > MAX_DEPTH) { + if (finiteJsonDepth && ++this.depth > MAX_DEPTH) { throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c); } Object current = mapper.createObject(); diff --git a/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java b/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java index 07912f28..04a4ea9b 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java @@ -2,10 +2,12 @@ import net.minidev.json.JSONArray; import net.minidev.json.JSONValue; +import net.minidev.json.parser.JSONParser; import net.minidev.json.parser.ParseException; +import static net.minidev.json.parser.JSONParser.DEFAULT_PERMISSIVE_MODE; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.Test; @@ -28,7 +30,27 @@ public void stressTest() throws Exception { assertEquals(e.getErrorType(), ParseException.ERROR_UNEXPECTED_JSON_DEPTH); return; } - assertTrue(false); + fail(); + } + + @Test + public void shouldNotFailWhenInfiniteJsonDepth() throws Exception { + int size = 500; + StringBuilder sb = new StringBuilder(10 + size*4); + for (int i=0; i < size; i++) { + sb.append("{a:"); + } + sb.append("true"); + for (int i=0; i < size; i++) { + sb.append("}"); + } + String s = sb.toString(); + try { + JSONParser parser = new JSONParser(DEFAULT_PERMISSIVE_MODE & ~JSONParser.FINITE_JSON_DEPTH); + parser.parse(s, JSONValue.defaultReader.DEFAULT); + } catch (ParseException e) { + fail(); + } } @Test From b50106e0ac075e9d718dcf918dbeb055df99bb7d Mon Sep 17 00:00:00 2001 From: ZhangJian He Date: Sat, 8 Jul 2023 15:24:50 +0800 Subject: [PATCH 2/3] remove extra new line --- .../src/main/java/net/minidev/json/parser/JSONParserBase.java | 1 - 1 file changed, 1 deletion(-) diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java index acff3506..f83cfaab 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java @@ -91,7 +91,6 @@ abstract class JSONParserBase { protected final boolean useIntegerStorage; protected final boolean reject127; protected final boolean unrestictBigDigit; - protected final boolean finiteJsonDepth; public JSONParserBase(int permissiveMode) { From 0a35821f956ccb3e9cd4c556f86d8c028b5f6fc3 Mon Sep 17 00:00:00 2001 From: ZhangJian He Date: Sun, 9 Jul 2023 16:46:15 +0800 Subject: [PATCH 3/3] bump the version --- accessors-smart/pom.xml | 2 +- json-smart-action/pom.xml | 4 ++-- json-smart/pom.xml | 4 ++-- .../src/main/java/net/minidev/json/parser/JSONParser.java | 2 +- .../main/java/net/minidev/json/parser/JSONParserBase.java | 8 ++++---- .../src/test/java/net/minidev/json/test/TestOverflow.java | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/accessors-smart/pom.xml b/accessors-smart/pom.xml index e1217643..834a9d51 100644 --- a/accessors-smart/pom.xml +++ b/accessors-smart/pom.xml @@ -17,7 +17,7 @@ limitations under the License. 4.0.0 net.minidev accessors-smart - 2.4.11 + 2.5.0 ASM based accessors helper used by json-smart Java reflect give poor performance on getter setter an constructor calls, accessors-smart use ASM to speed up those calls. bundle diff --git a/json-smart-action/pom.xml b/json-smart-action/pom.xml index b71b2020..552e61c1 100644 --- a/json-smart-action/pom.xml +++ b/json-smart-action/pom.xml @@ -2,7 +2,7 @@ 4.0.0 net.minidev json-smart-action - 2.4.11 + 2.5.0 JSON-smart-action Small and Fast Parser JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language. bundle @@ -245,7 +245,7 @@ net.minidev json-smart - 2.4.11 + 2.5.0 diff --git a/json-smart/pom.xml b/json-smart/pom.xml index 909231c2..5cc7a02b 100644 --- a/json-smart/pom.xml +++ b/json-smart/pom.xml @@ -17,7 +17,7 @@ limitations under the License. 4.0.0 net.minidev json-smart - 2.4.11 + 2.5.0 JSON Small and Fast Parser JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on a subset of the JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999. JSON is a text format that is completely language independent but uses conventions that are familiar to programmers of the C-family of languages, including C, C++, C#, Java, JavaScript, Perl, Python, and many others. These properties make JSON an ideal data-interchange language. bundle @@ -260,7 +260,7 @@ limitations under the License. net.minidev accessors-smart - 2.4.11 + 2.5.0 diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java index 482eac04..50daf9fb 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParser.java @@ -99,7 +99,7 @@ public class JSONParser { * * @since 2.5 */ - public static final int FINITE_JSON_DEPTH = 4096; + public static final int LIMIT_JSON_DEPTH = 4096; /** diff --git a/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java b/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java index f83cfaab..2f00d265 100644 --- a/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java +++ b/json-smart/src/main/java/net/minidev/json/parser/JSONParserBase.java @@ -91,7 +91,7 @@ abstract class JSONParserBase { protected final boolean useIntegerStorage; protected final boolean reject127; protected final boolean unrestictBigDigit; - protected final boolean finiteJsonDepth; + protected final boolean limitJsonDepth; public JSONParserBase(int permissiveMode) { this.acceptNaN = (permissiveMode & JSONParser.ACCEPT_NAN) > 0; @@ -108,7 +108,7 @@ public JSONParserBase(int permissiveMode) { this.checkTaillingSpace = (permissiveMode & JSONParser.ACCEPT_TAILLING_SPACE) == 0; this.reject127 = (permissiveMode & JSONParser.REJECT_127_CHAR) > 0; this.unrestictBigDigit = (permissiveMode & JSONParser.BIG_DIGIT_UNRESTRICTED) > 0; - this.finiteJsonDepth = (permissiveMode & JSONParser.FINITE_JSON_DEPTH) > 0; + this.limitJsonDepth = (permissiveMode & JSONParser.LIMIT_JSON_DEPTH) > 0; } public void checkControleChar() throws ParseException { @@ -298,7 +298,7 @@ protected Number parseNumber(String s) throws ParseException { protected T readArray(JsonReaderI mapper) throws ParseException, IOException { if (c != '[') throw new RuntimeException("Internal Error"); - if (finiteJsonDepth && ++this.depth > MAX_DEPTH) { + if (limitJsonDepth && ++this.depth > MAX_DEPTH) { throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c); } Object current = mapper.createArray(); @@ -555,7 +555,7 @@ protected T readObject(JsonReaderI mapper) throws ParseException, IOExcep // if (c != '{') throw new RuntimeException("Internal Error"); - if (finiteJsonDepth && ++this.depth > MAX_DEPTH) { + if (limitJsonDepth && ++this.depth > MAX_DEPTH) { throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c); } Object current = mapper.createObject(); diff --git a/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java b/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java index 04a4ea9b..9dd35419 100644 --- a/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java +++ b/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java @@ -46,7 +46,7 @@ public void shouldNotFailWhenInfiniteJsonDepth() throws Exception { } String s = sb.toString(); try { - JSONParser parser = new JSONParser(DEFAULT_PERMISSIVE_MODE & ~JSONParser.FINITE_JSON_DEPTH); + JSONParser parser = new JSONParser(DEFAULT_PERMISSIVE_MODE & ~JSONParser.LIMIT_JSON_DEPTH); parser.parse(s, JSONValue.defaultReader.DEFAULT); } catch (ParseException e) { fail();