Skip to content

Commit 12d6fe9

Browse files
bojandmarcospb19
authored andcommitted
enhance: add supposer for zstd skippable frames
1 parent 3c78fcf commit 12d6fe9

File tree

3 files changed

+34
-2
lines changed

3 files changed

+34
-2
lines changed

src/matchers/archive.rs

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use core::convert::TryInto;
2+
13
/// Returns whether a buffer is an ePub.
24
pub fn is_epub(buf: &[u8]) -> bool {
35
crate::book::is_epub(buf)
@@ -199,9 +201,33 @@ pub fn is_dcm(buf: &[u8]) -> bool {
199201
buf.len() > 131 && buf[128] == 0x44 && buf[129] == 0x49 && buf[130] == 0x43 && buf[131] == 0x4D
200202
}
201203

204+
const ZSTD_SKIP_START: usize = 0x184D2A50;
205+
const ZSTD_SKIP_MASK: usize = 0xFFFFFFF0;
206+
202207
/// Returns whether a buffer is a Zstd archive.
208+
// Zstandard compressed data is made of one or more frames.
209+
// There are two frame formats defined by Zstandard: Zstandard frames and Skippable frames.
210+
// See more details from https://tools.ietf.org/id/draft-kucherawy-dispatch-zstd-00.html#rfc.section.2
203211
pub fn is_zst(buf: &[u8]) -> bool {
204-
buf.len() > 3 && buf[0] == 0x28 && buf[1] == 0xB5 && buf[2] == 0x2F && buf[3] == 0xFD
212+
if buf.len() > 3 && buf[0] == 0x28 && buf[1] == 0xB5 && buf[2] == 0x2F && buf[3] == 0xFD {
213+
return true;
214+
}
215+
216+
if buf.len() < 8 {
217+
return false;
218+
}
219+
220+
let magic = u32::from_le_bytes(buf[0..4].try_into().unwrap()) as usize;
221+
if magic & ZSTD_SKIP_MASK == ZSTD_SKIP_START {
222+
let data_len = u32::from_le_bytes(buf[4..8].try_into().unwrap()) as usize;
223+
if buf.len() < 8 + data_len {
224+
return false;
225+
}
226+
let next_frame = &buf[8 + data_len..];
227+
return is_zst(next_frame);
228+
}
229+
230+
return false;
205231
}
206232

207233
/// Returns whether a buffer is a MSI Windows Installer archive.

testdata/sample.skippable.zst

105 Bytes
Binary file not shown.

tests/archive.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,11 @@ test_format!(
99
);
1010

1111
test_format!(Archive, "application/zstd", "zst", zst, "sample.tar.zst");
12-
1312
test_format!(Archive, "application/x-cpio", "cpio", cpio, "sample.cpio");
13+
test_format!(
14+
Archive,
15+
"application/zstd",
16+
"zst",
17+
zst_skip,
18+
"sample.skippable.zst"
19+
);

0 commit comments

Comments
 (0)