From 5c4486b9f58a83f283868135138f6ff3741b8c12 Mon Sep 17 00:00:00 2001 From: Looly Date: Tue, 5 Sep 2023 14:32:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DJSONUtil.parse()=E6=BA=A2?= =?UTF-8?q?=E5=87=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +- .../cn/hutool/core/collection/ListUtil.java | 7 ++-- .../java/cn/hutool/core/lang/Validator.java | 19 +++++++++ .../main/java/cn/hutool/json/JSONArray.java | 7 ++-- .../main/java/cn/hutool/json/JSONParser.java | 3 +- .../main/java/cn/hutool/json/JSONTokener.java | 39 ++++++++++++++++++- .../java/cn/hutool/json/Issue3289Test.java | 23 +++++++++++ 7 files changed, 90 insertions(+), 11 deletions(-) create mode 100755 hutool-json/src/test/java/cn/hutool/json/Issue3289Test.java diff --git a/CHANGELOG.md b/CHANGELOG.md index d91d38a88..188c3828b 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.22(2023-09-01) +# 5.8.22(2023-09-05) ### 🐣新特性 * 【core 】 NumberUtil.nullToZero增加重载(issue#I7PPD2@Gitee) @@ -30,6 +30,7 @@ * 【core 】 修复fillColumns空指针问题(issue#3284@Github) * 【core 】 修复Convert不能转换Optional和Opt问题(issue#I7WJHH@Gitee) * 【core 】 修复DateUtil.age年龄计算问题(issue#I7XMYW@Gitee) +* 【core 】 修复JSONUtil.parse()溢出问题(issue#3289@Github) ------------------------------------------------------------------------------------------------------------- # 5.8.21(2023-07-29) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java index a4f5ccda3..829a5b147 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java @@ -5,6 +5,7 @@ import cn.hutool.core.comparator.PropertyComparator; import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Matcher; +import cn.hutool.core.lang.Validator; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.PageUtil; @@ -432,10 +433,8 @@ public class ListUtil { if (index < size) { list.set(index, element); } else { - // issue#3286, 增加安全检查,最多增加2倍 - if(index > (list.size() + 1) * 2) { - throw new UtilException("Index is too large:", index); - } + // issue#3286, 增加安全检查,最多增加10倍 + Validator.checkIndexLimit(index, list.size()); for (int i = size; i < index; i++) { list.add(paddingElement); } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Validator.java b/hutool-core/src/main/java/cn/hutool/core/lang/Validator.java index 54f39209f..5551832ff 100755 --- a/hutool-core/src/main/java/cn/hutool/core/lang/Validator.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/Validator.java @@ -1257,4 +1257,23 @@ public class Validator { } return value; } + + /** + * 检查给定的index是否超出长度限制,默认检查超出倍数(10倍),此方法主要用于内部,检查包括: + * + * + * @param index 索引 + * @param size 数组、列表长度 + * @since 5.8.22 + */ + public static void checkIndexLimit(final int index, final int size) { + // issue#3286, 增加安全检查,最多增加10倍 + if (index > (size + 1) * 10) { + throw new ValidateException("Index [{}] is too large for size: [{}]", index, size); + } + } } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java index 6669cd5d0..f567b043d 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java @@ -3,6 +3,7 @@ package cn.hutool.json; import cn.hutool.core.bean.BeanPath; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Filter; +import cn.hutool.core.lang.Validator; import cn.hutool.core.lang.mutable.Mutable; import cn.hutool.core.lang.mutable.MutableObj; import cn.hutool.core.lang.mutable.MutablePair; @@ -457,10 +458,8 @@ public class JSONArray implements JSON, JSONGetter, List, Rando InternalJSONUtil.testValidity(element); this.rawList.add(index, JSONUtil.wrap(element, this.config)); } else { - // issue#3286, 增加安全检查,最多增加2倍 - if(index > (this.size() + 1) * 2) { - throw new JSONException("Index is too large:", index); - } + // issue#3286, 增加安全检查,最多增加10倍 + Validator.checkIndexLimit(index, this.size()); while (index != this.size()) { this.add(JSONNull.NULL); } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONParser.java b/hutool-json/src/main/java/cn/hutool/json/JSONParser.java index fef631bfa..3b1becd3a 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONParser.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONParser.java @@ -1,5 +1,6 @@ package cn.hutool.json; +import cn.hutool.core.lang.Console; import cn.hutool.core.lang.Filter; import cn.hutool.core.lang.mutable.Mutable; import cn.hutool.core.lang.mutable.MutablePair; @@ -66,7 +67,7 @@ public class JSONParser { } default: tokener.back(); - key = tokener.nextValue().toString(); + key = tokener.nextStringValue(); } // The key is followed by ':'. diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONTokener.java b/hutool-json/src/main/java/cn/hutool/json/JSONTokener.java index 2b8caf7b7..effbbcb0c 100755 --- a/hutool-json/src/main/java/cn/hutool/json/JSONTokener.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONTokener.java @@ -322,6 +322,43 @@ public class JSONTokener { } } + /** + * 获取下一个String格式的值,用户获取key + * @return String格式的值 + * @since 5.8.22 + */ + public String nextStringValue(){ + char c = this.nextClean(); + + switch (c) { + case '"': + case '\'': + return this.nextString(c); + case '{': + case '[': + throw this.syntaxError("Sting value must be not begin with a '{' or '['"); + } + + /* + * Handle unquoted text. This could be the values true, false, or null, or it can be a number. + * An implementation (such as this one) is allowed to also accept non-standard forms. Accumulate + * characters until we reach the end of the text or a formatting character. + */ + + final StringBuilder sb = new StringBuilder(); + while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { + sb.append(c); + c = this.next(); + } + this.back(); + + final String string = sb.toString().trim(); + if (string.isEmpty()) { + throw this.syntaxError("Missing value"); + } + return string; + } + /** * 获得下一个值,值类型可以是Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the JSONObject.NULL * @@ -366,7 +403,7 @@ public class JSONTokener { this.back(); string = sb.toString().trim(); - if (0 == string.length()) { + if (string.isEmpty()) { throw this.syntaxError("Missing value"); } return InternalJSONUtil.stringToValue(string); diff --git a/hutool-json/src/test/java/cn/hutool/json/Issue3289Test.java b/hutool-json/src/test/java/cn/hutool/json/Issue3289Test.java new file mode 100755 index 000000000..cd938dc92 --- /dev/null +++ b/hutool-json/src/test/java/cn/hutool/json/Issue3289Test.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package cn.hutool.json; + +import org.junit.Test; + +public class Issue3289Test { + @Test(expected = JSONException.class) + public void parseTest() { + final String s = "{\"a\":1,[6E962756779]}"; + JSONUtil.parse(s); + } +}