mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-01 05:37:23 -06:00
.ai import: a Zstandard frame that ends in a zero byte keeps it
The reader cut every trailing zero byte off the Zstandard editing data before decoding it, to drop the padding after the last frame. A frame can end in a zero byte itself (a raw or RLE block, or a checksum whose last byte is zero), and cutting it left the frame short, so the file failed to open with "its Zstandard compression is damaged". The reader now decodes frame after frame and stops when only zeros are left.
This commit is contained in:
@@ -158,11 +158,11 @@ impl Codec {
|
||||
flate2::read::ZlibDecoder::new(data).take(max + 1).read_to_end(&mut out).map_err(|_| damaged("its zlib compression"))?;
|
||||
}
|
||||
Codec::Zstd => {
|
||||
// The data may be several frames one after the other, padded with zeros.
|
||||
let end = data.iter().rposition(|b| *b != 0).map_or(0, |i| i + 1);
|
||||
let mut src = data.get(..end).unwrap_or_default();
|
||||
// The data may be several frames one after the other, padded with zeros. A frame
|
||||
// can itself end in a zero byte, so the padding is what is left after the last frame.
|
||||
let mut src = data;
|
||||
let mut frames = 0usize;
|
||||
while !src.is_empty() {
|
||||
while src.iter().any(|b| *b != 0) {
|
||||
frames += 1;
|
||||
if frames > MAX_FRAMES {
|
||||
return Err(damaged("its Zstandard compression"));
|
||||
|
||||
@@ -1472,6 +1472,19 @@ fn many_zstandard_frames_are_read_in_one_pass_and_capped() {
|
||||
assert!(started.elapsed() < std::time::Duration::from_secs(20), "{:?}", started.elapsed());
|
||||
}
|
||||
|
||||
/// A Zstandard frame that ends in a zero byte keeps it: only the zeros after the last frame are
|
||||
/// padding.
|
||||
#[test]
|
||||
fn a_zstandard_frame_ending_in_a_zero_byte_is_read_whole() {
|
||||
// Magic number, a single-segment header with a 1-byte content size of 3, and one raw block
|
||||
// (last, 3 bytes) holding `ab` and a zero byte.
|
||||
let frame = [0x28, 0xB5, 0x2F, 0xFD, 0x20, 3, 0x19, 0, 0, b'a', b'b', 0];
|
||||
for padding in [0, 64] {
|
||||
let raw = [&b"%AI24_ZStandard_Data"[..], &frame, &frame, &vec![0; padding]].concat();
|
||||
assert_eq!(decode_private(&raw).unwrap(), b"ab\0ab\0");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn closing_brackets_without_their_opening_dont_rescan_the_stack() {
|
||||
let n = 200_000;
|
||||
|
||||
Reference in New Issue
Block a user