Improve extension installation (#48518)
Mikayla Maki
,
Max
, and
Piotr
created
Release Notes:
- N/A
Co-authored-by: Max <max@zed.dev>
Co-authored-by: Piotr <piotr@zed.dev>
Change summary
crates/util/src/archive.rs | 42 ++++++++++++++++++++++++++++-----------
1 file changed, 30 insertions(+), 12 deletions(-)
Detailed changes
@@ -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<R: AsyncRead + Unpin>(destination: &Path, reader: R) -> Result<()> {
let mut reader = read::stream::ZipFileReader::new(BufReader::new(reader));
@@ -17,12 +26,17 @@ pub async fn extract_zip<R: AsyncRead + Unpin>(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<R: AsyncRead + AsyncSeek + Unpin>(
.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()