From e8030aea4a22dc3521b6b5911a87d986406935f3 Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Thu, 5 Feb 2026 13:37:18 -0800 Subject: [PATCH] Improve extension installation (#48518) Release Notes: - N/A Co-authored-by: Max Co-authored-by: Piotr --- crates/util/src/archive.rs | 42 +++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/crates/util/src/archive.rs b/crates/util/src/archive.rs index 540127a13804a84bca6e678de0a36ad5eea6347b..32be212f5e1589c8b8d516a7149bd712452e6851 100644 --- a/crates/util/src/archive.rs +++ b/crates/util/src/archive.rs @@ -6,6 +6,15 @@ use async_zip::base::read; use futures::AsyncSeek; use futures::{AsyncRead, io::BufReader}; +fn archive_path_is_normal(filename: &str) -> bool { + Path::new(filename).components().all(|c| { + matches!( + c, + std::path::Component::Normal(_) | std::path::Component::CurDir + ) + }) +} + #[cfg(windows)] pub async fn extract_zip(destination: &Path, reader: R) -> Result<()> { let mut reader = read::stream::ZipFileReader::new(BufReader::new(reader)); @@ -17,12 +26,17 @@ pub async fn extract_zip(destination: &Path, reader: R) -> while let Some(mut item) = reader.next_with_entry().await? { let entry_reader = item.reader_mut(); let entry = entry_reader.entry(); - let path = destination.join( - entry - .filename() - .as_str() - .context("reading zip entry file name")?, - ); + let filename = entry + .filename() + .as_str() + .context("reading zip entry file name")?; + + if !archive_path_is_normal(filename) { + reader = item.skip().await.context("reading next zip entry")?; + continue; + } + + let path = destination.join(filename); if entry .dir() @@ -79,12 +93,16 @@ pub async fn extract_seekable_zip( .canonicalize() .unwrap_or_else(|_| destination.to_path_buf()); for (i, entry) in reader.file().entries().to_vec().into_iter().enumerate() { - let path = destination.join( - entry - .filename() - .as_str() - .context("reading zip entry file name")?, - ); + let filename = entry + .filename() + .as_str() + .context("reading zip entry file name")?; + + if !archive_path_is_normal(filename) { + continue; + } + + let path = destination.join(filename); if entry .dir()