Skip to content

Commit

Permalink
Move LZMA properties parsing into rc-zip, remove unused dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
fasterthanlime committed Feb 2, 2024
1 parent 7a82225 commit c6d0980
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 43 deletions.
3 changes: 0 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ members = [
"rc-zip",
"rc-zip-sync",
"rc-zip-tokio",
]
]
4 changes: 4 additions & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 0 additions & 1 deletion rc-zip-sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
32 changes: 1 addition & 31 deletions rc-zip-sync/src/entry_reader/lzma_dec.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -101,37 +99,9 @@ where
}

pub(crate) fn mk_decoder(
mut r: RawEntryReader,
r: RawEntryReader,
uncompressed_size: u64,
) -> std::io::Result<impl Decoder<RawEntryReader>> {
// 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::<LittleEndian>()?;

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)),
Expand Down
2 changes: 1 addition & 1 deletion rc-zip-sync/src/entry_reader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand Down
2 changes: 0 additions & 2 deletions rc-zip/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
80 changes: 76 additions & 4 deletions rc-zip/src/format/local.rs
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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
Expand All @@ -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 {
Expand All @@ -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)?;
Expand All @@ -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,
Expand All @@ -60,6 +86,7 @@ impl LocalFileHeaderRecord {
uncompressed_size,
name,
extra,
method_specific,
})
}

Expand Down Expand Up @@ -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<Self> {
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(())
}
}

0 comments on commit c6d0980

Please sign in to comment.