diff --git a/CVE-2023-1370.patch b/CVE-2023-1370.patch new file mode 100644 index 0000000000000000000000000000000000000000..c7892153f44f34ef5afbab9d7e81cd5f4a9162fd --- /dev/null +++ b/CVE-2023-1370.patch @@ -0,0 +1,156 @@ +From: UrielCh +Date: Sun, 5 Mar 2023 13:01:10 +0200 +Subject: CVE-2023-1370: stack overflow due to excessive recursion +MIME-Version: 1.0 +Content-Type: text/plain; charset="utf-8" +Content-Transfer-Encoding: 8bit + +When reaching a ‘[‘ or ‘{‘ character in the JSON input, the code +parses an array or an object respectively. It was discovered that the +code does not have any limit to the nesting of such arrays or +objects. Since the parsing of nested arrays and objects is done +recursively, nesting too many of them can cause a stack exhaustion +(stack overflow) and crash the software. + +origin: https://github.com/netplex/json-smart-v2/commit/5b3205d051952d3100aa0db1535f6ba6226bd87a.patch +bug: https://research.jfrog.com/vulnerabilities/stack-exhaustion-in-json-smart-leads-to-denial-of-service-when-parsing-malformed-json-xray-427633/ +bug-debian: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1033474 +--- + .../net/minidev/json/parser/JSONParserBase.java | 17 +++++++++++++- + .../net/minidev/json/parser/ParseException.java | 9 +++++++- + .../java/net/minidev/json/test/TestOverflow.java | 27 ++++++++++++++++++++++ + 3 files changed, 51 insertions(+), 2 deletions(-) + create mode 100644 json-smart/src/test/java/net/minidev/json/test/TestOverflow.java + +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 96d6bb6..f65b8c5 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 +@@ -20,6 +20,7 @@ import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_EOF; + import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_LEADING_0; + import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_TOKEN; + import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_UNICODE; ++import static net.minidev.json.parser.ParseException.ERROR_UNEXPECTED_JSON_DEPTH; + + import java.io.IOException; + import java.math.BigDecimal; +@@ -39,6 +40,12 @@ import net.minidev.json.writer.JsonReaderI; + */ + abstract class JSONParserBase { + protected char c; ++ /** ++ * hard coded maximal depth for JSON parsing ++ */ ++ public final static int MAX_DEPTH = 400; ++ protected int depth = 0; ++ + JsonReader base; + public final static byte EOI = 0x1A; + protected static final char MAX_STOP = 126; // '}' -> 125 +@@ -232,9 +239,12 @@ abstract class JSONParserBase { + abstract protected void read() throws IOException; + + protected T readArray(JsonReaderI mapper) throws ParseException, IOException { +- Object current = mapper.createArray(); + if (c != '[') + throw new RuntimeException("Internal Error"); ++ if (++this.depth > MAX_DEPTH) { ++ throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c); ++ } ++ Object current = mapper.createArray(); + read(); + boolean needData = false; + // +@@ -249,6 +259,7 @@ abstract class JSONParserBase { + case ']': + if (needData && !acceptUselessComma) + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); ++ this.depth--; + read(); /* unstack */ + // + return mapper.convert(current); +@@ -485,6 +496,9 @@ abstract class JSONParserBase { + // + if (c != '{') + throw new RuntimeException("Internal Error"); ++ if (++this.depth > MAX_DEPTH) { ++ throw new ParseException(pos, ERROR_UNEXPECTED_JSON_DEPTH, c); ++ } + Object current = mapper.createObject(); + boolean needData = false; + boolean acceptData = true; +@@ -504,6 +518,7 @@ abstract class JSONParserBase { + case '}': + if (needData && !acceptUselessComma) + throw new ParseException(pos, ERROR_UNEXPECTED_CHAR, (char) c); ++ this.depth--; + read(); /* unstack */ + // + return mapper.convert(current); +diff --git a/json-smart/src/main/java/net/minidev/json/parser/ParseException.java b/json-smart/src/main/java/net/minidev/json/parser/ParseException.java +index e652cf2..42f11f2 100644 +--- a/json-smart/src/main/java/net/minidev/json/parser/ParseException.java ++++ b/json-smart/src/main/java/net/minidev/json/parser/ParseException.java +@@ -1,7 +1,7 @@ + package net.minidev.json.parser; + + /* +- * Copyright 2011 JSON-SMART authors ++ * Copyright 2011-2023 JSON-SMART authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. +@@ -30,6 +30,7 @@ public class ParseException extends Exception { + public static final int ERROR_UNEXPECTED_UNICODE = 4; + public static final int ERROR_UNEXPECTED_DUPLICATE_KEY = 5; + public static final int ERROR_UNEXPECTED_LEADING_0 = 6; ++ public static final int ERROR_UNEXPECTED_JSON_DEPTH = 7; + + private int errorType; + private Object unexpectedObject; +@@ -114,6 +115,12 @@ public class ParseException extends Exception { + sb.append(" at position "); + sb.append(position); + sb.append("."); ++ } else if (errorType == ERROR_UNEXPECTED_JSON_DEPTH) { ++ sb.append("Malicious payload, having non natural depths, parsing stoped on "); ++ sb.append(unexpectedObject); ++ sb.append(" at position "); ++ sb.append(position); ++ sb.append("."); + } else { + sb.append("Unkown error at position "); + sb.append(position); +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 +new file mode 100644 +index 0000000..18b52e7 +--- /dev/null ++++ b/json-smart/src/test/java/net/minidev/json/test/TestOverflow.java +@@ -0,0 +1,27 @@ ++package net.minidev.json.test; ++ ++import junit.framework.TestCase; ++import net.minidev.json.JSONValue; ++import net.minidev.json.parser.ParseException; ++ ++public class TestOverflow extends TestCase { ++ public void testStress() throws Exception { ++ int size = 10000; ++ 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 { ++ JSONValue.parseWithException(s); ++ } catch (ParseException e) { ++ assertEquals(e.getErrorType(), ParseException.ERROR_UNEXPECTED_JSON_DEPTH); ++ return; ++ } ++ assertEquals(0,1); ++ } ++} diff --git a/json-smart.spec b/json-smart.spec index 359af3ae78e0c372eb0f7ed13aa801741cb3e141..661cfc402e8dcb679e9aed3ed8ab2d0c4034b46c 100644 --- a/json-smart.spec +++ b/json-smart.spec @@ -1,10 +1,11 @@ Name: json-smart Version: 2.2 -Release: 1 +Release: 2 Summary: A small and very fast json parser/generator for java License: ASL 2.0 URL: https://github.com/netplex/json-smart-v2 Source0: https://github.com/netplex/json-smart-v2/archive/%{version}.tar.gz +Patch0001: CVE-2023-1370.patch BuildRequires: maven-local mvn(junit:junit) mvn(org.apache.felix:maven-bundle-plugin) BuildRequires: mvn(org.ow2.asm:asm) mvn(org.sonatype.oss:oss-parent:pom:) BuildArch: noarch @@ -17,7 +18,7 @@ Summary: Javadoc for %{name} This package contains javadoc for %{name}. %prep -%setup -q -n %{name}-v2-%{version} +%autosetup -n %{name}-v2-%{version} -p1 %pom_remove_dep :json-smart-mini parent %pom_remove_plugin :maven-javadoc-plugin parent %pom_remove_plugin :maven-source-plugin parent @@ -47,5 +48,8 @@ rm accessors-smart/src/test/java/net/minidev/asm/TestDateConvert.java %license LICENSE.txt %changelog +* Tue Apr 04 2023 liyuxiang - 2.2-2 +- fix CVE-2023-1370 + * Mon Aug 24 2020 wangchong - 2.2-1 - package init