From c6d0980d43ef3b8b15e91081d8b86d9da9bb33ce Mon Sep 17 00:00:00 2001 From: Amos Wenger Date: Fri, 2 Feb 2024 11:17:36 +0100 Subject: [PATCH] Move LZMA properties parsing into rc-zip, remove unused dependencies --- Cargo.lock | 3 - Cargo.toml | 2 +- Justfile | 4 ++ rc-zip-sync/Cargo.toml | 1 - rc-zip-sync/src/entry_reader/lzma_dec.rs | 32 +--------- rc-zip-sync/src/entry_reader/mod.rs | 2 +- rc-zip/Cargo.toml | 2 - rc-zip/src/format/local.rs | 80 ++++++++++++++++++++++-- 8 files changed, 83 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 15987e9..763131c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -824,11 +824,9 @@ checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" name = "rc-zip" version = "2.0.1" dependencies = [ - "byteorder", "cfg-if", "chardetng", "chrono", - "crc32fast", "encoding_rs", "num_enum", "oem_cp", @@ -843,7 +841,6 @@ dependencies = [ name = "rc-zip-sync" version = "2.0.1" dependencies = [ - "byteorder", "bzip2", "cfg-if", "chrono", diff --git a/Cargo.toml b/Cargo.toml index c77b87a..4d79c02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,4 @@ members = [ "rc-zip", "rc-zip-sync", "rc-zip-tokio", -] \ No newline at end of file +] diff --git a/Justfile b/Justfile index 03efa18..75f16b4 100644 --- a/Justfile +++ b/Justfile @@ -10,6 +10,10 @@ check: test *args: cargo nextest run {{args}} --all-features +# Report unused dependencies: +udeps: + RUSTC_BOOTSTRAP=1 cargo udeps + # Run all tests with nextest and cargo-llvm-cov ci-test: #!/bin/bash -eux diff --git a/rc-zip-sync/Cargo.toml b/rc-zip-sync/Cargo.toml index ec7fe86..2ef1302 100644 --- a/rc-zip-sync/Cargo.toml +++ b/rc-zip-sync/Cargo.toml @@ -30,7 +30,6 @@ zstd = { version = "0.13.0", optional = true } oval = "2.0.0" crc32fast = "1.3.2" tracing = "0.1.40" -byteorder = "1.5.0" cfg-if = "1.0.0" winnow = "0.5.36" diff --git a/rc-zip-sync/src/entry_reader/lzma_dec.rs b/rc-zip-sync/src/entry_reader/lzma_dec.rs index 425e0ed..d42f4aa 100644 --- a/rc-zip-sync/src/entry_reader/lzma_dec.rs +++ b/rc-zip-sync/src/entry_reader/lzma_dec.rs @@ -1,6 +1,4 @@ -use byteorder::{LittleEndian, ReadBytesExt}; use lzma_rs::decompress::Stream; -use rc_zip::{Error, UnsupportedError}; use std::io::{Read, Write}; use crate::decoder::{Decoder, RawEntryReader}; @@ -101,37 +99,9 @@ where } pub(crate) fn mk_decoder( - mut r: RawEntryReader, + r: RawEntryReader, uncompressed_size: u64, ) -> std::io::Result> { - // TODO: move into rc-zip - - // see `appnote.txt` section 5.8 - - // major & minor version are each 1 byte - let major = r.read_u8()?; - let minor = r.read_u8()?; - - // properties size is a 2-byte little-endian integer - let properties_size = r.read_u16::()?; - - if (major, minor) != (2, 0) { - return Err( - Error::Unsupported(UnsupportedError::LzmaVersionUnsupported { minor, major }).into(), - ); - } - - const LZMA_PROPERTIES_SIZE: u16 = 5; - if properties_size != LZMA_PROPERTIES_SIZE { - return Err( - Error::Unsupported(UnsupportedError::LzmaPropertiesHeaderWrongSize { - expected: 5, - actual: properties_size, - }) - .into(), - ); - } - let memlimit = 128 * 1024 * 1024; let opts = lzma_rs::decompress::Options { unpacked_size: lzma_rs::decompress::UnpackedSize::UseProvided(Some(uncompressed_size)), diff --git a/rc-zip-sync/src/entry_reader/mod.rs b/rc-zip-sync/src/entry_reader/mod.rs index 2b0c02d..94a663f 100644 --- a/rc-zip-sync/src/entry_reader/mod.rs +++ b/rc-zip-sync/src/entry_reader/mod.rs @@ -282,7 +282,7 @@ where Method::Lzma => { cfg_if! { if #[cfg(feature = "lzma")] { - Box::new(lzma_dec::mk_decoder(raw_r,self.inner.uncompressed_size)?) + Box::new(lzma_dec::mk_decoder(raw_r, self.inner.uncompressed_size)?) } else { return Err(Error::method_not_enabled(self.method)); } diff --git a/rc-zip/Cargo.toml b/rc-zip/Cargo.toml index 5822b9f..65284b0 100644 --- a/rc-zip/Cargo.toml +++ b/rc-zip/Cargo.toml @@ -21,11 +21,9 @@ pretty-hex = "0.4.1" oval = "2.0.0" chrono = "0.4.33" encoding_rs = "0.8.33" -crc32fast = "1.3.2" tracing = "0.1.40" oem_cp = "2.0.0" thiserror = "1.0.56" chardetng = "0.1.17" num_enum = "0.7.2" -byteorder = "1.5.0" cfg-if = "1.0.0" diff --git a/rc-zip/src/format/local.rs b/rc-zip/src/format/local.rs index 553b3e1..2c43c43 100644 --- a/rc-zip/src/format/local.rs +++ b/rc-zip/src/format/local.rs @@ -1,7 +1,8 @@ -use crate::format::*; +use crate::{format::*, Error, UnsupportedError}; use winnow::{ - binary::{le_u16, le_u32, le_u64}, + binary::{le_u16, le_u32, le_u64, le_u8}, combinator::opt, + error::{ContextError, ErrMode, ErrorKind, FromExternalError}, seq, token::tag, PResult, Parser, Partial, @@ -15,7 +16,7 @@ pub struct LocalFileHeaderRecord { /// general purpose bit flag pub flags: u16, /// compression method - pub method: u16, + pub method: Method, /// last mod file datetime pub modified: MsdosTimestamp, /// crc-32 @@ -28,6 +29,16 @@ pub struct LocalFileHeaderRecord { pub name: ZipString, // extra field pub extra: ZipBytes, + + // method-specific fields + pub method_specific: MethodSpecific, +} + +#[derive(Debug)] +/// Method-specific properties following the local file header +pub enum MethodSpecific { + None, + Lzma(LzmaProperties), } impl LocalFileHeaderRecord { @@ -38,7 +49,7 @@ impl LocalFileHeaderRecord { let reader_version = Version::parser.parse_next(i)?; let flags = le_u16.parse_next(i)?; - let method = le_u16.parse_next(i)?; + let method = le_u16.parse_next(i).map(Method::from)?; let modified = MsdosTimestamp::parser.parse_next(i)?; let crc32 = le_u32.parse_next(i)?; let compressed_size = le_u32.parse_next(i)?; @@ -50,6 +61,21 @@ impl LocalFileHeaderRecord { let name = ZipString::parser(name_len).parse_next(i)?; let extra = ZipBytes::parser(extra_len).parse_next(i)?; + let method_specific = match method { + Method::Lzma => { + let lzma_properties = LzmaProperties::parser.parse_next(i)?; + if let Err(e) = lzma_properties.error_if_unsupported() { + return Err(ErrMode::Cut(ContextError::from_external_error( + i, + ErrorKind::Verify, + e, + ))); + } + MethodSpecific::Lzma(lzma_properties) + } + _ => MethodSpecific::None, + }; + Ok(Self { reader_version, flags, @@ -60,6 +86,7 @@ impl LocalFileHeaderRecord { uncompressed_size, name, extra, + method_specific, }) } @@ -114,3 +141,48 @@ impl DataDescriptorRecord { } } } + +/// 5.8.5 LZMA Properties header +#[derive(Debug)] +pub struct LzmaProperties { + /// major version + pub major: u8, + /// minor version + pub minor: u8, + /// properties size + pub properties_size: u16, +} + +impl LzmaProperties { + pub fn parser(i: &mut Partial<&'_ [u8]>) -> PResult { + seq! {Self { + major: le_u8, + minor: le_u8, + properties_size: le_u16, + }} + .parse_next(i) + } + + pub fn error_if_unsupported(&self) -> Result<(), Error> { + if (self.major, self.minor) != (2, 0) { + return Err(Error::Unsupported( + UnsupportedError::LzmaVersionUnsupported { + minor: self.minor, + major: self.major, + }, + )); + } + + const LZMA_PROPERTIES_SIZE: u16 = 5; + if self.properties_size != LZMA_PROPERTIES_SIZE { + return Err(Error::Unsupported( + UnsupportedError::LzmaPropertiesHeaderWrongSize { + expected: 5, + actual: self.properties_size, + }, + )); + } + + Ok(()) + } +}