fix: Rare bug where find_and_parse would give up prematurely on detecting a false end-of-CDR header

This commit is contained in:
Chris Hennick 2024-04-29 13:18:17 -07:00
parent 0513fbcc6b
commit 42972297f1
No known key found for this signature in database
GPG key ID: DA47AABA4961C509
2 changed files with 22 additions and 2 deletions

View file

@ -70,7 +70,9 @@ impl CentralDirectoryEnd {
BYTES_BETWEEN_MAGIC_AND_COMMENT_SIZE as i64, BYTES_BETWEEN_MAGIC_AND_COMMENT_SIZE as i64,
))?; ))?;
let cde_start_pos = reader.seek(io::SeekFrom::Start(pos))?; let cde_start_pos = reader.seek(io::SeekFrom::Start(pos))?;
return CentralDirectoryEnd::parse(reader).map(|cde| (cde, cde_start_pos)); if let Ok(end_header) = CentralDirectoryEnd::parse(reader) {
return Ok((end_header, cde_start_pos));
}
} }
pos = match pos.checked_sub(1) { pos = match pos.checked_sub(1) {
Some(p) => p, Some(p) => p,

View file

@ -1715,9 +1715,10 @@ mod test {
use crate::result::ZipResult; use crate::result::ZipResult;
use crate::types::DateTime; use crate::types::DateTime;
use crate::write::SimpleFileOptions; use crate::write::SimpleFileOptions;
use crate::CompressionMethod::Stored;
use crate::ZipArchive; use crate::ZipArchive;
use std::io; use std::io;
use std::io::{Read, Write}; use std::io::{Cursor, Read, Write};
use std::path::PathBuf; use std::path::PathBuf;
#[test] #[test]
@ -2199,4 +2200,21 @@ mod test {
assert_eq!(file.name(), "sleep"); assert_eq!(file.name(), "sleep");
assert_eq!(file.data_start(), page_size.into()); assert_eq!(file.data_start(), page_size.into());
} }
#[test]
fn test_crash_short_read() {
let mut writer = ZipWriter::new(Cursor::new(Vec::new()));
let comment: Vec<u8> = vec![
1, 80, 75, 5, 6, 237, 237, 237, 237, 237, 237, 237, 237, 44, 255, 191, 255, 255, 255,
255, 255, 255, 255, 255, 16,
];
writer.set_raw_comment(comment);
let options = SimpleFileOptions::default()
.compression_method(Stored)
.with_alignment(11823);
writer.start_file("", options).unwrap();
writer.write_all(&[255, 255, 44, 255, 0]).unwrap();
let written = writer.finish().unwrap();
let new_writer = ZipWriter::new_append(written).unwrap();
}
} }