Bug fix: LZMA state is large, so put it in a Box

This commit is contained in:
Chris Hennick 2024-04-11 13:28:37 -07:00
parent 812498e788
commit 4f3f2d1fca
4 changed files with 27 additions and 20 deletions

View file

@ -82,10 +82,10 @@ pub(crate) mod zip_archive {
}
}
#[cfg(feature = "lzma")]
use crate::read::lzma::LzmaDecoder;
use crate::result::ZipError::InvalidPassword;
pub use zip_archive::ZipArchive;
#[cfg(feature = "lzma")]
use crate::read::lzma::LzmaReader;
#[allow(clippy::large_enum_variant)]
pub(crate) enum CryptoReader<'a> {
@ -153,7 +153,7 @@ pub(crate) enum ZipFileReader<'a> {
#[cfg(feature = "zstd")]
Zstd(Crc32Reader<ZstdDecoder<'a, io::BufReader<CryptoReader<'a>>>>),
#[cfg(feature = "lzma")]
Lzma(Crc32Reader<LzmaReader<CryptoReader<'a>>>),
Lzma(Crc32Reader<Box<LzmaDecoder<CryptoReader<'a>>>>),
}
impl<'a> Read for ZipFileReader<'a> {
@ -176,7 +176,7 @@ impl<'a> Read for ZipFileReader<'a> {
#[cfg(feature = "zstd")]
ZipFileReader::Zstd(r) => r.read(buf),
#[cfg(feature = "lzma")]
ZipFileReader::Lzma(r) => r.read(buf)
ZipFileReader::Lzma(r) => r.read(buf),
}
}
}
@ -329,8 +329,8 @@ pub(crate) fn make_reader(
}
#[cfg(feature = "lzma")]
CompressionMethod::Lzma => {
let reader = LzmaReader::new(reader);
ZipFileReader::Lzma(Crc32Reader::new(reader, crc32, ae2_encrypted))
let reader = LzmaDecoder::new(reader);
ZipFileReader::Lzma(Crc32Reader::new(Box::new(reader), crc32, ae2_encrypted))
}
_ => panic!("Compression method not supported"),
}

View file

@ -1,6 +1,6 @@
use lzma_rs::decompress::{Options, Stream, UnpackedSize};
use std::collections::VecDeque;
use std::io::{copy, Error, Read, Result, Write};
use lzma_rs::decompress::{Options, Stream, UnpackedSize};
const COMPRESSED_BYTES_TO_BUFFER: usize = 4096;
@ -11,26 +11,26 @@ const OPTIONS: Options = Options {
};
#[derive(Debug)]
pub struct LzmaReader<R> {
pub struct LzmaDecoder<R> {
compressed_reader: R,
stream: Stream<VecDeque<u8>>
stream: Stream<VecDeque<u8>>,
}
impl <R: Read> LzmaReader<R> {
impl<R: Read> LzmaDecoder<R> {
pub fn new(inner: R) -> Self {
LzmaReader {
LzmaDecoder {
compressed_reader: inner,
stream: Stream::new_with_options(&OPTIONS, VecDeque::new())
stream: Stream::new_with_options(&OPTIONS, VecDeque::new()),
}
}
pub fn finish(mut self) -> Result<VecDeque<u8>> {
copy(&mut self.compressed_reader, &mut self.stream)?;
self.stream.finish().map_err(Error::from)
}
}
impl <R: Read> Read for LzmaReader<R> {
impl<R: Read> Read for LzmaDecoder<R> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let mut bytes_read = self.stream.get_output_mut().unwrap().read(buf)?;
while bytes_read < buf.len() {
@ -39,9 +39,14 @@ impl <R: Read> Read for LzmaReader<R> {
if compressed_bytes_read == 0 {
break;
}
self.stream.write_all(&next_compressed[..compressed_bytes_read])?;
bytes_read += self.stream.get_output_mut().unwrap().read(&mut buf[bytes_read..])?;
self.stream
.write_all(&next_compressed[..compressed_bytes_read])?;
bytes_read += self
.stream
.get_output_mut()
.unwrap()
.read(&mut buf[bytes_read..])?;
}
Ok(bytes_read)
}
}
}

View file

@ -129,7 +129,7 @@ pub(crate) mod zip_writer {
pub(super) flush_on_finish_file: bool,
}
}
use crate::result::ZipError::{InvalidArchive};
use crate::result::ZipError::InvalidArchive;
#[cfg(feature = "lzma")]
use crate::result::ZipError::UnsupportedArchive;
use crate::write::GenericZipWriter::{Closed, Storer};
@ -1272,7 +1272,9 @@ impl<W: Write + Seek> GenericZipWriter<W> {
}))
}
#[cfg(feature = "lzma")]
CompressionMethod::Lzma => Err(UnsupportedArchive("LZMA isn't supported for compression")),
CompressionMethod::Lzma => {
Err(UnsupportedArchive("LZMA isn't supported for compression"))
}
CompressionMethod::Unsupported(..) => {
Err(ZipError::UnsupportedArchive("Unsupported compression"))
}

View file

@ -18,4 +18,4 @@ fn decompress_lzma() {
file.read_to_end(&mut content)
.expect("couldn't read encrypted and compressed file");
assert_eq!("Hello world\n", String::from_utf8(content).unwrap());
}
}