From d821c410c6de49055c38695671c2055797f045c4 Mon Sep 17 00:00:00 2001 From: TouyamaRie Date: Fri, 28 Nov 2025 16:04:46 +0800 Subject: [PATCH 1/2] Fix issue 4167 --- .../java/cn/hutool/core/util/HexUtil.java | 15 +++++++-- .../java/cn/hutool/core/util/HexUtilTest.java | 31 +++++++++++++++++++ 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java index 0f209c483..1083e2897 100755 --- a/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/HexUtil.java @@ -379,15 +379,24 @@ public class HexUtil { * @return 格式化后的字符串 */ public static String format(final String hexStr, String prefix) { + if (StrUtil.isEmpty(hexStr)) { + return StrUtil.EMPTY; + } if (null == prefix) { prefix = StrUtil.EMPTY; } final int length = hexStr.length(); final StringBuilder builder = StrUtil.builder(length + length / 2 + (length / 2 * prefix.length())); - builder.append(prefix).append(hexStr.charAt(0)).append(hexStr.charAt(1)); - for (int i = 2; i < length - 1; i += 2) { - builder.append(CharUtil.SPACE).append(prefix).append(hexStr.charAt(i)).append(hexStr.charAt(i + 1)); + + for (int i = 0; i < length; i++) { + if (i % 2 == 0) { + if (i != 0) { + builder.append(CharUtil.SPACE); + } + builder.append(prefix); + } + builder.append(hexStr.charAt(i)); } return builder.toString(); } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/HexUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/HexUtilTest.java index b37f4b3ff..f8e7a0745 100755 --- a/hutool-core/src/test/java/cn/hutool/core/util/HexUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/HexUtilTest.java @@ -116,4 +116,35 @@ public class HexUtilTest { final String hex3 = "#FF"; assertEquals(new BigInteger("FF", 16), HexUtil.toBigInteger(hex3)); } + + @Test + public void testFormatEmpty() { + String result = HexUtil.format(""); + assertEquals("", result); + } + + @Test + public void testFormatSingleChar() { + String result = HexUtil.format("1"); + assertEquals("1", result); + } + + @Test + public void testFormatOddLength() { + String result = HexUtil.format("123"); + assertEquals("12 3", result); + } + + @Test + public void testFormatWithPrefixSingleChar() { + String result = HexUtil.format("1", "0x"); + assertEquals("0x1", result); + } + + @Test + public void testFormatWithPrefixOddLength() { + String result = HexUtil.format("123", "0x"); + assertEquals("0x12 0x3", result); + } + } From 0f60aa021a3d3a2a3623a208638e51d727f72edb Mon Sep 17 00:00:00 2001 From: TouyamaRie Date: Fri, 28 Nov 2025 17:15:18 +0800 Subject: [PATCH 2/2] Fix issue 4169 --- .../cn/hutool/core/text/split/SplitIter.java | 39 +++++++++---------- .../hutool/core/text/split/SplitIterTest.java | 16 ++++++++ 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/text/split/SplitIter.java b/hutool-core/src/main/java/cn/hutool/core/text/split/SplitIter.java index b1cb444d9..f24760af4 100644 --- a/hutool-core/src/main/java/cn/hutool/core/text/split/SplitIter.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/split/SplitIter.java @@ -71,29 +71,28 @@ public class SplitIter extends ComputeIter implements Serializable { return text.substring(offset); } - final int start = finder.start(offset); - // 无分隔符,结束 - if (start < 0) { - // 如果不再有分隔符,但是遗留了字符,则单独作为一个段 - if (offset <= text.length()) { - final String result = text.substring(offset); - if (false == ignoreEmpty || false == result.isEmpty()) { - // 返回非空串 - offset = Integer.MAX_VALUE; - return result; + String result = null; + int start; + do { + start = finder.start(offset); + // 无分隔符,结束 + if (start < 0) { + // 如果不再有分隔符,但是遗留了字符,则单独作为一个段 + if (offset <= text.length()) { + result = text.substring(offset); + if (!ignoreEmpty || !result.isEmpty()) { + // 返回非空串 + offset = Integer.MAX_VALUE; + return result; + } } + return null; } - return null; - } - // 找到新的分隔符位置 - final String result = text.substring(offset, start); - offset = finder.end(start); - - if (ignoreEmpty && result.isEmpty()) { - // 发现空串且需要忽略时,跳过之 - return computeNext(); - } + // 找到新的分隔符位置 + result = text.substring(offset, start); + offset = finder.end(start); + } while (ignoreEmpty && result.isEmpty()); // 空串则继续循环 count++; return result; diff --git a/hutool-core/src/test/java/cn/hutool/core/text/split/SplitIterTest.java b/hutool-core/src/test/java/cn/hutool/core/text/split/SplitIterTest.java index 01ad2d157..c82fae99f 100644 --- a/hutool-core/src/test/java/cn/hutool/core/text/split/SplitIterTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/text/split/SplitIterTest.java @@ -6,6 +6,8 @@ import cn.hutool.core.text.finder.PatternFinder; import cn.hutool.core.text.finder.StrFinder; import org.junit.jupiter.api.Test; +import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.regex.Pattern; @@ -153,4 +155,18 @@ public class SplitIterTest { assertEquals(1, strings.size()); }); } + + @Test + public void issue4169Test() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 20000; i++) { // 1万次连续分隔符,模拟递归深度风险场景 + sb.append(","); + } + sb.append("test"); + + SplitIter iter = new SplitIter(sb.toString(), new StrFinder(",",false), 0, true); + List result = iter.toList(false); + + assertEquals(Collections.singletonList("test"), result); + } }