diff --git a/Cargo.toml b/Cargo.toml index 9e18484..896bfe5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -150,10 +150,10 @@ tree_magic_mini = "3.2" content_inspector = "0.2.4" rustc-hash = "2.1.1" term_size = "0.3.2" -bzip2 = "0.5.2" -zip = "2.4.2" +bzip2-rs = "0.1.2" +zip = { version = "2.4.2", default-features = false, features = ["deflate", "deflate64", "time"] } tar = "0.4.44" -xz2 = "0.1.7" +lzma-rs = "0.3.0" asar = "0.3.0" blake3 = "1.8.2" memchr = "2.7" diff --git a/src/decompress.rs b/src/decompress.rs index de04d27..937bb1a 100644 --- a/src/decompress.rs +++ b/src/decompress.rs @@ -1,18 +1,18 @@ use std::{ fs, - io::Read, + io::{BufReader, Read}, path::{Component, Path, PathBuf}, }; use anyhow::Result; use asar::AsarReader; -use bzip2::read::BzDecoder; +use bzip2_rs::DecoderReader; use flate2::read::{GzDecoder, ZlibDecoder}; +use lzma_rs::xz_decompress; use memmap2::Mmap; use tar::Archive; use tempfile::{tempdir, TempDir}; use uuid::Uuid; -use xz2::read::XzDecoder; use zip::ZipArchive; /// Formats that are basically a ZIP container. @@ -184,6 +184,17 @@ fn stream_to_file(mut decoder: R, out_path: &Path) -> Result Result { + if !is_safe_extract_path(out_path) { + anyhow::bail!("unsafe path during decompression: {}", out_path.display()); + } + let input = fs::File::open(path)?; + let mut reader = BufReader::new(input); + let mut out_file = fs::File::create(out_path)?; + xz_decompress(&mut reader, &mut out_file)?; + Ok(CompressedContent::RawFile(out_path.to_owned())) +} + /* ─────────────────────────────────────────────────────────────── one *step* of decompression ───────────────────────────────────────────────────────────── */ @@ -221,13 +232,12 @@ fn decompress_once(path: &Path, base_dir: Option<&Path>) -> Result { let out_path = make_output_path(path, base_dir, "decomp.tar"); - let decoder = BzDecoder::new(fs::File::open(path)?); + let decoder = DecoderReader::new(fs::File::open(path)?); return stream_to_file(decoder, &out_path); } "xz" => { let out_path = make_output_path(path, base_dir, "decomp.tar"); - let decoder = XzDecoder::new(fs::File::open(path)?); - return stream_to_file(decoder, &out_path); + return stream_xz_to_file(path, &out_path); } "zlib" => { let out_path = make_output_path(path, base_dir, "decomp.tar");