This is an automated email from the ASF dual-hosted git repository.
jimin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git
The following commit(s) were added to refs/heads/2.x by this push:
new c83ab1f8c3 optimize: zstd decompression is changed from jni to
ZstdInputStream (#7578)
c83ab1f8c3 is described below
commit c83ab1f8c32d68fd54d266d426981590eb5bc18b
Author: funkye <[email protected]>
AuthorDate: Sat Aug 9 16:44:06 2025 +0800
optimize: zstd decompression is changed from jni to ZstdInputStream (#7578)
---
changes/en-us/2.x.md | 1 +
changes/zh-cn/2.x.md | 2 ++
.../org/apache/seata/compressor/zstd/ZstdUtil.java | 22 +++++++++++++---
.../apache/seata/compressor/zstd/ZstdUtilTest.java | 30 ++++++++++++++++++++--
4 files changed, 49 insertions(+), 6 deletions(-)
diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 27aa56d535..7f1add0791 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -39,6 +39,7 @@ Add changes here for all PR submitted to the 2.x branch.
- [[#7478](https://github.com/apache/incubator-seata/pull/7484)] optimize:
remove client id metric
- [[#7557](https://github.com/seata/seata/pull/7557)] upgrade some npmjs
dependencies
- [[#7577](https://github.com/seata/seata/pull/7577)] remove the 4MB size
limit when decompressing with zstd
+- [[#7578](https://github.com/seata/seata/pull/7578)] zstd decompression is
changed from jni to ZstdInputStream
### security:
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 2b0947bdb0..70abe17143 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -48,6 +48,8 @@
- [[#7541](https://github.com/seata/seata/pull/7541)] 修复 jakarta 依赖在 jdk17+
单测失败问题
- [[#7540](https://github.com/seata/seata/pull/7540)] 修复mock server端口冲突问题
+- [[#7578](https://github.com/seata/seata/pull/7578)]
zstd解压由jni改为ZstdInputStream
+
### refactor:
diff --git
a/compressor/seata-compressor-zstd/src/main/java/org/apache/seata/compressor/zstd/ZstdUtil.java
b/compressor/seata-compressor-zstd/src/main/java/org/apache/seata/compressor/zstd/ZstdUtil.java
index 6dcc2c7885..b9c92b6238 100644
---
a/compressor/seata-compressor-zstd/src/main/java/org/apache/seata/compressor/zstd/ZstdUtil.java
+++
b/compressor/seata-compressor-zstd/src/main/java/org/apache/seata/compressor/zstd/ZstdUtil.java
@@ -17,6 +17,11 @@
package org.apache.seata.compressor.zstd;
import com.github.luben.zstd.Zstd;
+import com.github.luben.zstd.ZstdInputStream;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
/**
* the Zstd Util
@@ -28,6 +33,7 @@ public class ZstdUtil {
if (bytes == null) {
throw new NullPointerException("bytes is null");
}
+
return Zstd.compress(bytes);
}
@@ -35,9 +41,17 @@ public class ZstdUtil {
if (bytes == null) {
throw new NullPointerException("bytes is null");
}
- long size = Zstd.decompressedSize(bytes);
- byte[] decompressBytes = new byte[(int) size];
- Zstd.decompress(decompressBytes, bytes);
- return decompressBytes;
+ try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ZstdInputStream zis = new ZstdInputStream(bais);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
+ byte[] buffer = new byte[8192];
+ int len;
+ while ((len = zis.read(buffer)) > 0) {
+ baos.write(buffer, 0, len);
+ }
+ return baos.toByteArray();
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Failed to decompress zstd
data", e);
+ }
}
}
diff --git
a/compressor/seata-compressor-zstd/src/test/java/org/apache/seata/compressor/zstd/ZstdUtilTest.java
b/compressor/seata-compressor-zstd/src/test/java/org/apache/seata/compressor/zstd/ZstdUtilTest.java
index 4bc94f9617..d46bd48bfb 100644
---
a/compressor/seata-compressor-zstd/src/test/java/org/apache/seata/compressor/zstd/ZstdUtilTest.java
+++
b/compressor/seata-compressor-zstd/src/test/java/org/apache/seata/compressor/zstd/ZstdUtilTest.java
@@ -17,7 +17,6 @@
package org.apache.seata.compressor.zstd;
import com.github.luben.zstd.Zstd;
-import com.github.luben.zstd.ZstdException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -47,7 +46,7 @@ public class ZstdUtilTest {
@Test
public void test_decompress_with_len_illegal() {
- Assertions.assertThrows(ZstdException.class, () -> {
+ Assertions.assertThrows(IllegalArgumentException.class, () -> {
//
https://github.com/facebook/zstd/blob/dev/doc/zstd_compression_format.md#zstandard-frames
List<Byte> bytes = new ArrayList<>();
byte[] magic = new byte[] {(byte) 0x28, (byte) 0xB5, (byte) 0x2F,
(byte) 0xFD};
@@ -82,4 +81,31 @@ public class ZstdUtilTest {
byte[] decompressedData = ZstdUtil.decompress(compressedData);
Assertions.assertEquals(len, decompressedData.length);
}
+
+ @Test
+ public void test_decompress_with_fake_frame_content_size_oom() {
+ // Construct a fake zstd header with the frame content size set to
1GB, while the actual content is only 4MB.
+ byte[] magic = new byte[] {(byte) 0x28, (byte) 0xB5, (byte) 0x2F,
(byte) 0xFD};
+ byte[] frameHeaderDescriptor = new byte[magic.length + 1];
+ System.arraycopy(magic, 0, frameHeaderDescriptor, 0, magic.length);
+ frameHeaderDescriptor[magic.length] = (byte) 0xA0;
+ // frame content size: 1GB = 0x40000000
+ byte[] frameContentSize = new byte[] {(byte) 0x00, (byte) 0x00, (byte)
0x00, (byte) 0x40};
+ // The actual content is only 4MB.
+ byte[] fakeContent = new byte[4 * 1024 * 1024];
+ for (int i = 0; i < fakeContent.length; i++) {
+ fakeContent[i] = (byte) ('A' + i % 26);
+ }
+ byte[] frameContent = new byte[frameHeaderDescriptor.length +
frameContentSize.length + fakeContent.length];
+ System.arraycopy(frameHeaderDescriptor, 0, frameContent, 0,
frameHeaderDescriptor.length);
+ System.arraycopy(frameContentSize, 0, frameContent,
frameHeaderDescriptor.length, frameContentSize.length);
+ System.arraycopy(
+ fakeContent,
+ 0,
+ frameContent,
+ frameHeaderDescriptor.length + frameContentSize.length,
+ fakeContent.length);
+ Assertions.assertThrows(IllegalArgumentException.class, () ->
ZstdUtil.decompress(frameContent));
+ Assertions.assertTrue(Zstd.decompressedSize(frameContent) >
MAX_COMPRESSED_SIZE);
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]