Open
Description
Describe the bug
Have a look at the following (at least close to) minimal example:
use std::{fs::File, io::Write};
use zip::{write::SimpleFileOptions, ZipWriter};
fn write(w: &mut dyn Write, size: usize) {
let chunks = 1 << 20;
let mut written = 0;
let buf = vec![0x21; chunks];
while written < size {
let to_write = (size - written).min(chunks);
w.write_all(&buf[..to_write]).unwrap();
written += to_write;
}
}
fn main() {
let path = "foo.zip";
let file = File::create(path).unwrap();
let mut writer = ZipWriter::new(file);
let opts = SimpleFileOptions::default().compression_method(zip::CompressionMethod::Stored);
writer.start_file_from_path("close_to_4gb", opts).unwrap();
//let below = 1 << 6; //This works fine!
let below = 1 << 5; // This or smaller: broken
write(&mut writer, (4 << 30) - below);
writer.start_file_from_path("some_more", opts).unwrap();
write(&mut writer, 1);
std::mem::drop(writer);
let file = File::options().read(true).write(true).open(path).unwrap();
let mut writer = ZipWriter::new_append(file).unwrap();
writer.start_file_from_path("bad_stuff", opts).unwrap();
write(&mut writer, 1);
}
In short, we are writing a file close to 4GB into a zip file, then write another file (can be only 1 byte), then close the file, open it again to append to it, write another file.
The resulting file is broken and cannot be successfully unzip'ed.
To Reproduce
Steps to reproduce the behavior:
- Run the above code to create the archive
foo.zip
. - Try to unzip it:
unzip foo.zip
- Observe the error message occurring after writing the first file:
Archive: foo.zip
extracting: close_to_4gb
error: invalid zip file with overlapped components (possible zip bomb)
To unzip the file anyway, rerun the command with UNZIP_DISABLE_ZIPBOMB_DETECTION=TRUE environmnent variable
Additional context
The bug is present both in version 2.6.1 as well as current master (b3ea5b8).