VYPR
High severityNVD Advisory· Published Dec 27, 2023· Updated Apr 17, 2025

CVE-2023-51075

CVE-2023-51075

Description

hutool-core v5.8.23 was discovered to contain an infinite loop in the StrSplitter.splitByRegex function. This vulnerability allows attackers to cause a Denial of Service (DoS) via manipulation of the first two parameters.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Hutool-core v5.8.23 has an infinite loop in StrSplitter.splitByRegex that causes OOM or stack overflow when given empty string parameters, enabling DoS attacks.

Vulnerability

Description

CVE-2023-51073 affects Hutool-core, a popular Java utility library. The StrSplitter.splitByRegex function in version 5.8.23 contains an infinite loop when called with empty strings for both the str and regex parameters (the first two arguments). This root cause is a missing boundary check for empty inputs, causing the function to never terminate and continuously allocate memory [1].

Attack

Vector and Exploitation

An attacker can trigger this flaw by directly calling StrSplitter.splitByRegex("", "", 0, false, true) or similar combinations where both input strings are empty. The vulnerability requires no authentication, special privileges, or network access beyond the ability to influence the arguments passed to this method. In applications that accept user-controlled strings for splitting (e.g., parsing user input, configuration data), a remote or local attacker can supply empty strings to cause a denial of service [1][2]. The issue is independent of the remaining parameters (limit, ignoreCase, trim).

Impact

Exploitation leads to uncontrolled resource consumption: either an OutOfMemoryError (OOM) due to heap exhaustion (from repeatedly adding to a list in an infinite loop) or a StackOverflowError if infinite recursion occurs. This effectively causes application or service unavailability, making it a classic denial-of-service vulnerability [1].

Mitigation

Status

The Hutool project has fixed this issue in commit 32f2d0bd55defecb869fbf64d940bcc05642accc, which updates StrSplitter.splitByRegex to handle empty string inputs correctly by returning an empty list early [4]. Users should upgrade to a patched version (e.g., 5.8.24 or later). No workaround exists other than avoiding empty string inputs to this function until an upgrade is applied. The CVE has been assigned CVSSv4 metrics, though NVD has not yet provided a score [2].

AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
cn.hutool:hutool-coreMaven
< 5.8.245.8.24

Affected products

2

Patches

1
32f2d0bd55de

修复StrSplitter.splitByRegex使用空参数导致的OOM问题

https://github.com/dromara/hutoolLoolyDec 11, 2023via ghsa
3 files changed · +40 16
  • CHANGELOG.md+2 1 modified
    @@ -2,7 +2,7 @@
     # 🚀Changelog
     
     -------------------------------------------------------------------------------------------------------------
    -# 5.8.24(2023-12-11)
    +# 5.8.24(2023-12-12)
     
     ### 🐣新特性
     * 【cache 】      Cache增加get重载,可自定义超时时间(issue#I8G0DL@Gitee)
    @@ -18,6 +18,7 @@
     * 【extra 】      修复Archiver 最后一个 Entry 为空文件夹时未关闭 Entry问题(pr#1123@Gitee)
     * 【core  】      修复ImgUtil.convert png转jpg在jdk9+中失败问题(issue#I8L8UA@Gitee)
     * 【cache 】      修复StampedCache的get方法非原子问题(issue#I8MEIX@Gitee)
    +* 【core  】      修复StrSplitter.splitByRegex使用空参数导致的OOM问题(issue#3421@Github)
     
     -------------------------------------------------------------------------------------------------------------
     # 5.8.23(2023-11-12)
    
  • hutool-core/src/main/java/cn/hutool/core/text/finder/PatternFinder.java+9 2 modified
    @@ -49,9 +49,16 @@ public TextFinder setNegative(boolean negative) {
     	@Override
     	public int start(int from) {
     		if (matcher.find(from)) {
    +			final int end = matcher.end();
     			// 只有匹配到的字符串结尾在limit范围内,才算找到
    -			if(matcher.end() <= getValidEndIndex()){
    -				return matcher.start();
    +			if(end <= getValidEndIndex()){
    +				final int start = matcher.start();
    +				if(start == end){
    +					// issue#3421,如果匹配空串,按照未匹配对待,避免死循环
    +					return INDEX_NOT_FOUND;
    +				}
    +
    +				return start;
     			}
     		}
     		return INDEX_NOT_FOUND;
    
  • hutool-core/src/test/java/cn/hutool/core/text/split/StrSplitterTest.java+29 13 modified
    @@ -1,5 +1,6 @@
     package cn.hutool.core.text.split;
     
    +import cn.hutool.core.collection.ListUtil;
     import cn.hutool.core.text.StrSplitter;
     import org.junit.Assert;
     import org.junit.Test;
    @@ -15,49 +16,49 @@ public class StrSplitterTest {
     
     	@Test
     	public void splitByCharTest(){
    -		String str1 = "a, ,efedsfs,   ddf";
    -		List<String> split = StrSplitter.split(str1, ',', 0, true, true);
    +		final String str1 = "a, ,efedsfs,   ddf";
    +		final List<String> split = StrSplitter.split(str1, ',', 0, true, true);
     
     		Assert.assertEquals("ddf", split.get(2));
     		Assert.assertEquals(3, split.size());
     	}
     
     	@Test
     	public void splitByStrTest(){
    -		String str1 = "aabbccaaddaaee";
    -		List<String> split = StrSplitter.split(str1, "aa", 0, true, true);
    +		final String str1 = "aabbccaaddaaee";
    +		final List<String> split = StrSplitter.split(str1, "aa", 0, true, true);
     		Assert.assertEquals("ee", split.get(2));
     		Assert.assertEquals(3, split.size());
     	}
     
     	@Test
     	public void splitByBlankTest(){
    -		String str1 = "aa bbccaa     ddaaee";
    -		List<String> split = StrSplitter.split(str1, 0);
    +		final String str1 = "aa bbccaa     ddaaee";
    +		final List<String> split = StrSplitter.split(str1, 0);
     		Assert.assertEquals("ddaaee", split.get(2));
     		Assert.assertEquals(3, split.size());
     	}
     
     	@Test
     	public void splitPathTest(){
    -		String str1 = "/use/local/bin";
    -		List<String> split = StrSplitter.splitPath(str1, 0);
    +		final String str1 = "/use/local/bin";
    +		final List<String> split = StrSplitter.splitPath(str1, 0);
     		Assert.assertEquals("bin", split.get(2));
     		Assert.assertEquals(3, split.size());
     	}
     
     	@Test
     	public void splitMappingTest() {
    -		String str = "1.2.";
    -		List<Long> split = StrSplitter.split(str, '.', 0, true, true, Long::parseLong);
    +		final String str = "1.2.";
    +		final List<Long> split = StrSplitter.split(str, '.', 0, true, true, Long::parseLong);
     		Assert.assertEquals(2, split.size());
     		Assert.assertEquals(Long.valueOf(1L), split.get(0));
     		Assert.assertEquals(Long.valueOf(2L), split.get(1));
     	}
     
     	@Test
     	public void splitEmptyTest(){
    -		String str = "";
    +		final String str = "";
     		final String[] split = str.split(",");
     		final String[] strings = StrSplitter.splitToArray(str, ",", -1, false, false);
     		Assert.assertNotNull(strings);
    @@ -66,7 +67,7 @@ public void splitEmptyTest(){
     
     	@Test
     	public void splitNullTest(){
    -		String str = null;
    +		final String str = null;
     		final String[] strings = StrSplitter.splitToArray(str, ",", -1, false, false);
     		Assert.assertNotNull(strings);
     		Assert.assertEquals(0, strings.length);
    @@ -77,7 +78,7 @@ public void splitNullTest(){
     	 */
     	@Test
     	public void splitByRegexTest(){
    -		String text = "01  821   34567890182345617821";
    +		final String text = "01  821   34567890182345617821";
     		List<String> strings = StrSplitter.splitByRegex(text, "21", 0, false, true);
     		Assert.assertEquals(2, strings.size());
     		Assert.assertEquals("01  8", strings.get(0));
    @@ -89,4 +90,19 @@ public void splitByRegexTest(){
     		Assert.assertEquals("   345678901823456178", strings.get(1));
     		Assert.assertEquals("", strings.get(2));
     	}
    +
    +	@Test
    +	public void issue3421Test() {
    +		List<String> strings = StrSplitter.splitByRegex("", "", 0, false, false);
    +		Assert.assertEquals(ListUtil.of(""), strings);
    +
    +		strings = StrSplitter.splitByRegex("aaa", "", 0, false, false);
    +		Assert.assertEquals(ListUtil.of("aaa"), strings);
    +
    +		strings = StrSplitter.splitByRegex("", "aaa", 0, false, false);
    +		Assert.assertEquals(ListUtil.of(""), strings);
    +
    +		strings = StrSplitter.splitByRegex("", "", 0, false, true);
    +		Assert.assertEquals(ListUtil.of(), strings);
    +	}
     }
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.