From 30fafaa5de4a2ec7f08eaa5f4eb25d1076bf7c19 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 5 Jan 2024 12:36:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0ParseConfig=EF=BC=8C=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E5=A2=9E=E5=8A=A0maxNestingDepth=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E9=81=BF=E5=85=8DStackOverflowError=E9=97=AE=E9=A2=98=EF=BC=8C?= =?UTF-8?q?=E4=BF=AE=E5=A4=8DCVE-2022-45688=E6=BC=8F=E6=B4=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hutool/json/xml/JSONXMLParser.java | 22 ++++++++++++++----- .../dromara/hutool/json/xml/ParseConfig.java | 2 +- .../hutool/json/xml/Issue2748Test.java | 18 +++++++++++++++ 3 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 hutool-json/src/test/java/org/dromara/hutool/json/xml/Issue2748Test.java diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLParser.java b/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLParser.java index dc8f579e3..524829c4a 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLParser.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/xml/JSONXMLParser.java @@ -39,20 +39,23 @@ public class JSONXMLParser { public static void parseJSONObject(final String xmlStr, final JSONObject jo, final ParseConfig parseConfig) throws JSONException { final XMLTokener x = new XMLTokener(xmlStr, jo.config()); while (x.more() && x.skipPast("<")) { - parse(x, jo, null, parseConfig); + parse(x, jo, null, parseConfig, 0); } } /** * 扫描XML内容,并解析到JSONObject中。 * - * @param x {@link XMLTokener} - * @param context {@link JSONObject} - * @param name 标签名,null表示从根标签开始解析 + * @param x {@link XMLTokener} + * @param context {@link JSONObject} + * @param name 标签名,null表示从根标签开始解析 + * @param parseConfig 解析选项 + * @param currentNestingDepth 当前层级 * @return {@code true}表示解析完成 * @throws JSONException JSON异常 */ - private static boolean parse(final XMLTokener x, final JSONObject context, final String name, final ParseConfig parseConfig) throws JSONException { + private static boolean parse(final XMLTokener x, final JSONObject context, final String name, + final ParseConfig parseConfig, final int currentNestingDepth) throws JSONException { final char c; int i; final JSONObject jsonobject; @@ -175,7 +178,14 @@ public class JSONXMLParser { } else if (token == XmlConstants.C_LT) { // Nested element - if (parse(x, jsonobject, tagName, parseConfig)) { + // issue#2748 of CVE-2022-45688 + final int maxNestingDepth = parseConfig.getMaxNestingDepth(); + if (maxNestingDepth > -1 && currentNestingDepth >= maxNestingDepth) { + throw x.syntaxError("Maximum nesting depth of " + maxNestingDepth + " reached"); + } + + // Nested element + if (parse(x, jsonobject, tagName, parseConfig, currentNestingDepth + 1)) { if (jsonobject.isEmpty()) { context.append(tagName, StrUtil.EMPTY); } else if (jsonobject.size() == 1 && jsonobject.get("content") != null) { diff --git a/hutool-json/src/main/java/org/dromara/hutool/json/xml/ParseConfig.java b/hutool-json/src/main/java/org/dromara/hutool/json/xml/ParseConfig.java index fbe4e1b51..d1fd7b33c 100644 --- a/hutool-json/src/main/java/org/dromara/hutool/json/xml/ParseConfig.java +++ b/hutool-json/src/main/java/org/dromara/hutool/json/xml/ParseConfig.java @@ -44,7 +44,7 @@ public class ParseConfig implements Serializable { /** * 最大嵌套深度,用于解析时限制解析层级,当大于这个层级时抛出异常,-1表示无限制 */ - private int maxNestingDepth; + private int maxNestingDepth = -1; /** * 是否保持值为String类型,如果为{@code false},则尝试转换为对应类型(numeric, boolean, string) diff --git a/hutool-json/src/test/java/org/dromara/hutool/json/xml/Issue2748Test.java b/hutool-json/src/test/java/org/dromara/hutool/json/xml/Issue2748Test.java new file mode 100644 index 000000000..8093101cd --- /dev/null +++ b/hutool-json/src/test/java/org/dromara/hutool/json/xml/Issue2748Test.java @@ -0,0 +1,18 @@ +package org.dromara.hutool.json.xml; + +import org.dromara.hutool.core.text.StrUtil; +import org.dromara.hutool.json.JSONException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class Issue2748Test { + + @Test + void toJSONObjectTest() { + final String s = StrUtil.repeat("", 600); + + Assertions.assertThrows(JSONException.class, () -> { + JSONXMLUtil.toJSONObject(s, ParseConfig.of().setMaxNestingDepth(512)); + }); + } +}