#![allow(clippy::unwrap_used, clippy::expect_used, clippy::doc_markdown)]
use std::io::{Cursor, Read, Write};
use std::path::PathBuf;
use zip::write::SimpleFileOptions;
use zip::{CompressionMethod as OracleMethod, ZipWriter};
use zip_core::{CompressionMethod, ZipArchive};
fn payload() -> Vec<u8> {
(0..20_000u32).map(|i| (i / 64) as u8).collect()
}
fn fixture(name: &str) -> Vec<u8> {
let path =
PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"), "/../tests/data/codecs")).join(name);
std::fs::read(&path).unwrap_or_else(|e| panic!("read fixture {}: {e}", path.display()))
}
fn oracle_decode(bytes: &[u8], name: &str) -> Vec<u8> {
let mut ar = zip::ZipArchive::new(Cursor::new(bytes.to_vec())).unwrap();
let mut e = ar.by_name(name).unwrap();
let mut out = Vec::new();
e.read_to_end(&mut out).unwrap();
out
}
fn assert_zip_core_decodes(bytes: &[u8], name: &str, method: CompressionMethod, expect: &[u8]) {
let mut ar = ZipArchive::new(Cursor::new(bytes.to_vec())).unwrap();
let mut e = ar.by_name(name).unwrap();
assert_eq!(e.compression(), method, "method for {name}");
let mut got = Vec::new();
e.read_to_end(&mut got).unwrap();
assert_eq!(got, expect, "decoded bytes for {name}");
}
#[test]
fn bzip2_decodes_byte_identical_to_oracle() {
let p = payload();
let mut zw = ZipWriter::new(Cursor::new(Vec::new()));
zw.start_file(
"file.bin",
SimpleFileOptions::default().compression_method(OracleMethod::Bzip2),
)
.unwrap();
zw.write_all(&p).unwrap();
let bytes = zw.finish().unwrap().into_inner();
assert_eq!(oracle_decode(&bytes, "file.bin"), p);
assert_zip_core_decodes(&bytes, "file.bin", CompressionMethod::Bzip2, &p);
}
#[test]
fn zstd_decodes_byte_identical_to_oracle() {
let p = payload();
let mut zw = ZipWriter::new(Cursor::new(Vec::new()));
zw.start_file(
"file.bin",
SimpleFileOptions::default().compression_method(OracleMethod::Zstd),
)
.unwrap();
zw.write_all(&p).unwrap();
let bytes = zw.finish().unwrap().into_inner();
assert_eq!(oracle_decode(&bytes, "file.bin"), p);
assert_zip_core_decodes(&bytes, "file.bin", CompressionMethod::Zstd, &p);
}
#[test]
fn deflate64_decodes_7z_fixture() {
let bytes = fixture("deflate64.zip");
assert_zip_core_decodes(&bytes, "file.bin", CompressionMethod::Deflate64, &payload());
}
#[test]
fn lzma_decodes_7z_fixture() {
let bytes = fixture("lzma.zip");
assert_zip_core_decodes(&bytes, "file.bin", CompressionMethod::Lzma, &payload());
}
#[test]
fn xz_decodes_method95_fixture() {
let bytes = fixture("xz.zip");
assert_zip_core_decodes(&bytes, "file.bin", CompressionMethod::Xz, &payload());
}
#[test]
fn deflate64_decodes_real_securitynik_ctf() {
let Ok(zip_path) = std::env::var("ZIP_CORE_REAL_DEFLATE64_ZIP") else {
eprintln!("skipping: ZIP_CORE_REAL_DEFLATE64_ZIP not set");
return;
};
let file = std::fs::File::open(&zip_path).unwrap();
let mut ar = ZipArchive::new(file).unwrap();
{
let json = "SECURITYNIK-WIN-20231116-235706.json";
let mut e = ar.by_name(json).unwrap();
assert_eq!(e.compression(), CompressionMethod::Deflate64);
let mut out = Vec::new();
e.read_to_end(&mut out).unwrap();
assert_eq!(out.len() as u64, e.size(), "decoded length vs CD size");
}
if std::env::var("ZIP_CORE_REAL_DEFLATE64_FULL").is_ok() {
let dmp = "SECURITYNIK-WIN-20231116-235706.dmp";
let mut d = ar.by_name(dmp).unwrap();
assert_eq!(d.compression(), CompressionMethod::Deflate64);
let n = std::io::copy(&mut d, &mut std::io::sink()).unwrap();
assert_eq!(n, d.size(), "decoded length vs CD size");
}
}