mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-12-07 01:28:34 +08:00
修复HexUtil.format在处理长度小于2的字符串会抛异常,在处理长度为奇数的字符串时最后一个字符会被忽略的问题 修复SplitIter.computeNext递归调用可能导致栈溢出风险
This commit is contained in:
parent
9a775ef3cf
commit
2369beed81
@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package cn.hutool.v7.core.codec.binary;
|
package cn.hutool.v7.core.codec.binary;
|
||||||
|
|
||||||
import cn.hutool.v7.core.text.CharUtil;
|
|
||||||
import cn.hutool.v7.core.text.StrUtil;
|
import cn.hutool.v7.core.text.StrUtil;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
@ -249,16 +248,42 @@ public class HexUtil extends Hex {
|
|||||||
* @param prefix 自定义前缀,如0x
|
* @param prefix 自定义前缀,如0x
|
||||||
* @return 格式化后的字符串
|
* @return 格式化后的字符串
|
||||||
*/
|
*/
|
||||||
public static String format(final String hexStr, String prefix) {
|
public static String format(final String hexStr, final String prefix) {
|
||||||
|
return format(hexStr, prefix, StrUtil.SPACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化Hex字符串,结果为每2位加一个空格,类似于:
|
||||||
|
* <pre>
|
||||||
|
* e8 8c 67 03 80 cb 22 00 95 26 8f
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @param hexStr Hex字符串
|
||||||
|
* @param prefix 自定义前缀,如0x
|
||||||
|
* @param separator 自定义分隔符,如空格
|
||||||
|
* @return 格式化后的字符串
|
||||||
|
*/
|
||||||
|
public static String format(final String hexStr, String prefix, String separator) {
|
||||||
|
if (StrUtil.isEmpty(hexStr)) {
|
||||||
|
return StrUtil.EMPTY;
|
||||||
|
}
|
||||||
if (null == prefix) {
|
if (null == prefix) {
|
||||||
prefix = StrUtil.EMPTY;
|
prefix = StrUtil.EMPTY;
|
||||||
}
|
}
|
||||||
|
if (null == separator) {
|
||||||
|
separator = StrUtil.SPACE;
|
||||||
|
}
|
||||||
|
|
||||||
final int length = hexStr.length();
|
final int length = hexStr.length();
|
||||||
final StringBuilder builder = StrUtil.builder(length + length / 2 + (length / 2 * prefix.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 = 0; i < length; i++) {
|
||||||
for (int i = 2; i < length - 1; i += 2) {
|
if (i % 2 == 0) {
|
||||||
builder.append(CharUtil.SPACE).append(prefix).append(hexStr.charAt(i)).append(hexStr.charAt(i + 1));
|
if (i != 0) {
|
||||||
|
builder.append(separator);
|
||||||
|
}
|
||||||
|
builder.append(prefix);
|
||||||
|
}
|
||||||
|
builder.append(hexStr.charAt(i));
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,12 +89,15 @@ public class SplitIter extends ComputeIter<String> implements Serializable {
|
|||||||
return text.substring(offset);
|
return text.substring(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
final int start = finder.start(offset);
|
String result;
|
||||||
|
int start;
|
||||||
|
do {
|
||||||
|
start = finder.start(offset);
|
||||||
// 无分隔符,结束
|
// 无分隔符,结束
|
||||||
if (start < 0) {
|
if (start < 0) {
|
||||||
// 如果不再有分隔符,但是遗留了字符,则单独作为一个段
|
// 如果不再有分隔符,但是遗留了字符,则单独作为一个段
|
||||||
if (offset <= text.length()) {
|
if (offset <= text.length()) {
|
||||||
final String result = text.substring(offset);
|
result = text.substring(offset);
|
||||||
if (!ignoreEmpty || !result.isEmpty()) {
|
if (!ignoreEmpty || !result.isEmpty()) {
|
||||||
// 返回非空串
|
// 返回非空串
|
||||||
offset = Integer.MAX_VALUE;
|
offset = Integer.MAX_VALUE;
|
||||||
@ -105,13 +108,9 @@ public class SplitIter extends ComputeIter<String> implements Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 找到新的分隔符位置
|
// 找到新的分隔符位置
|
||||||
final String result = text.substring(offset, start);
|
result = text.substring(offset, start);
|
||||||
offset = finder.end(start);
|
offset = finder.end(start);
|
||||||
|
} while (ignoreEmpty && result.isEmpty()); // 空串则继续循环
|
||||||
if (ignoreEmpty && result.isEmpty()) {
|
|
||||||
// 发现空串且需要忽略时,跳过之
|
|
||||||
return computeNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
@ -23,9 +23,12 @@ import cn.hutool.v7.core.text.finder.StrFinder;
|
|||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
public class SplitIterTest {
|
public class SplitIterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -38,7 +41,7 @@ public class SplitIterTest {
|
|||||||
Integer.MAX_VALUE,
|
Integer.MAX_VALUE,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
Assertions.assertEquals(6, splitIter.toList(false).size());
|
assertEquals(6, splitIter.toList(false).size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -51,7 +54,7 @@ public class SplitIterTest {
|
|||||||
Integer.MAX_VALUE,
|
Integer.MAX_VALUE,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
Assertions.assertEquals(4, splitIter.toList(false).size());
|
assertEquals(4, splitIter.toList(false).size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -65,7 +68,7 @@ public class SplitIterTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final List<String> strings = splitIter.toList(false);
|
final List<String> strings = splitIter.toList(false);
|
||||||
Assertions.assertEquals(4, strings.size());
|
assertEquals(4, strings.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -79,10 +82,10 @@ public class SplitIterTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final List<String> strings = splitIter.toList(true);
|
final List<String> strings = splitIter.toList(true);
|
||||||
Assertions.assertEquals(3, strings.size());
|
assertEquals(3, strings.size());
|
||||||
Assertions.assertEquals("a", strings.get(0));
|
assertEquals("a", strings.get(0));
|
||||||
Assertions.assertEquals("efedsfs", strings.get(1));
|
assertEquals("efedsfs", strings.get(1));
|
||||||
Assertions.assertEquals("ddf", strings.get(2));
|
assertEquals("ddf", strings.get(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -96,7 +99,7 @@ public class SplitIterTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final List<String> strings = splitIter.toList(false);
|
final List<String> strings = splitIter.toList(false);
|
||||||
Assertions.assertEquals(3, strings.size());
|
assertEquals(3, strings.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -110,7 +113,7 @@ public class SplitIterTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final List<String> strings = splitIter.toList(false);
|
final List<String> strings = splitIter.toList(false);
|
||||||
Assertions.assertEquals(3, strings.size());
|
assertEquals(3, strings.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -123,7 +126,7 @@ public class SplitIterTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final List<String> strings = splitIter.toList(false);
|
final List<String> strings = splitIter.toList(false);
|
||||||
Assertions.assertEquals(4, strings.size());
|
assertEquals(4, strings.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -136,7 +139,7 @@ public class SplitIterTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final List<String> strings = splitIter.toList(false);
|
final List<String> strings = splitIter.toList(false);
|
||||||
Assertions.assertEquals(3, strings.size());
|
assertEquals(3, strings.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -149,7 +152,7 @@ public class SplitIterTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final List<String> strings = splitIter.toList(false);
|
final List<String> strings = splitIter.toList(false);
|
||||||
Assertions.assertEquals(1, strings.size());
|
assertEquals(1, strings.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切割字符串是空字符串时报错
|
// 切割字符串是空字符串时报错
|
||||||
@ -164,7 +167,21 @@ public class SplitIterTest {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final List<String> strings = splitIter.toList(false);
|
final List<String> strings = splitIter.toList(false);
|
||||||
Assertions.assertEquals(1, strings.size());
|
assertEquals(1, strings.size());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void issue4169Test() {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < 20000; i++) { // 1万次连续分隔符,模拟递归深度风险场景
|
||||||
|
sb.append(",");
|
||||||
|
}
|
||||||
|
sb.append("test");
|
||||||
|
|
||||||
|
final SplitIter iter = new SplitIter(sb.toString(), new StrFinder(",",false), 0, true);
|
||||||
|
final List<String> result = iter.toList(false);
|
||||||
|
|
||||||
|
assertEquals(Collections.singletonList("test"), result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -135,4 +135,34 @@ public class HexUtilTest {
|
|||||||
final String hex3 = "#FF";
|
final String hex3 = "#FF";
|
||||||
assertEquals(new BigInteger("FF", 16), HexUtil.toBigInteger(hex3));
|
assertEquals(new BigInteger("FF", 16), HexUtil.toBigInteger(hex3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFormatEmpty() {
|
||||||
|
final String result = HexUtil.format("");
|
||||||
|
assertEquals("", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFormatSingleChar() {
|
||||||
|
final String result = HexUtil.format("1");
|
||||||
|
assertEquals("1", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFormatOddLength() {
|
||||||
|
final String result = HexUtil.format("123");
|
||||||
|
assertEquals("12 3", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFormatWithPrefixSingleChar() {
|
||||||
|
final String result = HexUtil.format("1", "0x");
|
||||||
|
assertEquals("0x1", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFormatWithPrefixOddLength() {
|
||||||
|
final String result = HexUtil.format("123", "0x");
|
||||||
|
assertEquals("0x12 0x3", result);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user