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

This commit is contained in:
Looly 2023-12-12 04:29:27 +08:00
parent f39d7c5393
commit 2a164a7692
3 changed files with 51 additions and 16 deletions

View File

@ -63,9 +63,16 @@ public class PatternFinder extends TextFinder {
@Override
public int start(final 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;

View File

@ -258,7 +258,12 @@ public class SplitUtil {
}
/**
* 通过正则切分字符串
* 通过正则切分字符串规则如下
* <ul>
* <li>当提供的str为{@code null}返回new ArrayList(0)</li>
* <li>当提供的str为{@code ""}返回[""]</li>
* <li>当提供的separatorRegex为empty(null or "")返回[str]即只有原串一个元素的数组</li>
* </ul>
*
* @param str 字符串
* @param separatorRegex 分隔符正则
@ -269,19 +274,19 @@ public class SplitUtil {
* @since 3.0.8
*/
public static List<String> splitByRegex(final CharSequence str, final String separatorRegex, final int limit, final boolean isTrim, final boolean ignoreEmpty) {
if (StrUtil.isEmpty(str)) {
return ListUtil.zero();
}
if(StrUtil.isEmpty(separatorRegex)){
return ListUtil.of(str.toString());
}
final Pattern pattern = PatternPool.get(separatorRegex);
return splitByRegex(str, pattern, limit, isTrim, ignoreEmpty);
return splitByRegex(str,
// 给定字符串或正则为empty就不再需要解析pattern
(StrUtil.isEmpty(str) || StrUtil.isEmpty(separatorRegex)) ? null : PatternPool.get(separatorRegex),
limit, isTrim, ignoreEmpty);
}
/**
* 通过正则切分字符串<br>
* 如果为空字符串或者null 则返回空集合
* 通过正则切分字符串规则如下
* <ul>
* <li>当提供的str为{@code null}返回new ArrayList(0)</li>
* <li>当提供的str为{@code ""}返回[""]</li>
* <li>当提供的separatorRegex为empty(null or "")返回[str]即只有原串一个元素的数组</li>
* </ul>
*
* @param str 字符串
* @param separatorPattern 分隔符正则{@link Pattern}
@ -292,11 +297,18 @@ public class SplitUtil {
* @since 3.0.8
*/
public static List<String> splitByRegex(final CharSequence str, final Pattern separatorPattern, final int limit, final boolean isTrim, final boolean ignoreEmpty) {
if (StrUtil.isEmpty(str)) {
if (null == str) {
return ListUtil.zero();
}
if(0 == str.length()){
return ignoreEmpty ? ListUtil.zero() : ListUtil.of(StrUtil.EMPTY);
}
if(null == separatorPattern){
return ListUtil.of(str.toString());
final String result = str.toString();
if(StrUtil.isEmpty(result)){
return ignoreEmpty ? ListUtil.zero() : ListUtil.of(StrUtil.EMPTY);
}
return ListUtil.of(result);
}
final SplitIter splitIter = new SplitIter(str, new PatternFinder(separatorPattern), limit, ignoreEmpty);
return splitIter.toList(isTrim);

View File

@ -14,10 +14,12 @@ package org.dromara.hutool.core.text.split;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.lang.Console;
import org.dromara.hutool.core.text.finder.PatternFinder;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.List;
import java.util.regex.Pattern;
/**
* {@link SplitUtil} 单元测试
@ -120,9 +122,23 @@ public class SplitUtilTest {
@Test
void issue3421Test() {
List<String> strings = SplitUtil.splitByRegex("", "", 0, false, false);
Assertions.assertEquals(ListUtil.empty(), strings);
Assertions.assertEquals(ListUtil.of(""), strings);
strings = SplitUtil.splitByRegex("aaa", "", 0, false, false);
Assertions.assertEquals(ListUtil.of("aaa"), strings);
strings = SplitUtil.splitByRegex("", "aaa", 0, false, false);
Assertions.assertEquals(ListUtil.of(""), strings);
strings = SplitUtil.splitByRegex("", "", 0, false, true);
Assertions.assertEquals(ListUtil.of(), strings);
}
@Test
void issue3421Test2() {
// 测试在无前置判断时是否死循环
final SplitIter splitIter = new SplitIter("", new PatternFinder(Pattern.compile("")), -1, false);
final List<String> list = splitIter.toList(false);
Assertions.assertEquals(ListUtil.of(""), list);
}
}