增加ParseConfig,通过增加maxNestingDepth参数避免StackOverflowError问题,修复CVE-2022-45688漏洞

This commit is contained in:
Looly 2024-01-05 12:36:23 +08:00
parent 69206406d7
commit 30fafaa5de
3 changed files with 35 additions and 7 deletions

View File

@ -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) {

View File

@ -44,7 +44,7 @@ public class ParseConfig implements Serializable {
/**
* 最大嵌套深度用于解析时限制解析层级当大于这个层级时抛出异常-1表示无限制
*/
private int maxNestingDepth;
private int maxNestingDepth = -1;
/**
* 是否保持值为String类型如果为{@code false}则尝试转换为对应类型(numeric, boolean, string)

View File

@ -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("<a>", 600);
Assertions.assertThrows(JSONException.class, () -> {
JSONXMLUtil.toJSONObject(s, ParseConfig.of().setMaxNestingDepth(512));
});
}
}