Validate content-length of downloaded extension tar gz files (#10430)

Release Notes:

- Fixed a bug where extension installation would appear to succeed even
if the download did not complete due to network interruptions
([#10330](https://github.com/zed-industries/zed/issues/10330)).

Co-authored-by: Marshall <marshall@zed.dev>
This commit is contained in:
Max Brunsfeld 2024-04-11 10:24:09 -07:00 committed by GitHub
parent bcd2ca6196
commit 47f698d5a3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 19 additions and 1 deletions

1
Cargo.lock generated
View file

@ -3579,6 +3579,7 @@ dependencies = [
"fs", "fs",
"futures 0.3.28", "futures 0.3.28",
"gpui", "gpui",
"isahc",
"language", "language",
"log", "log",
"lsp", "lsp",

View file

@ -23,6 +23,7 @@ collections.workspace = true
fs.workspace = true fs.workspace = true
futures.workspace = true futures.workspace = true
gpui.workspace = true gpui.workspace = true
isahc.workspace = true
language.workspace = true language.workspace = true
log.workspace = true log.workspace = true
lsp.workspace = true lsp.workspace = true

View file

@ -606,7 +606,23 @@ impl ExtensionStore {
) )
.await?; .await?;
let decompressed_bytes = GzipDecoder::new(BufReader::new(response.body_mut())); let content_length = response
.headers()
.get(isahc::http::header::CONTENT_LENGTH)
.and_then(|value| value.to_str().ok()?.parse::<usize>().ok());
let mut body = BufReader::new(response.body_mut());
let mut tgz_bytes = Vec::new();
body.read_to_end(&mut tgz_bytes).await?;
if let Some(content_length) = content_length {
let actual_len = tgz_bytes.len();
if content_length != actual_len {
bail!("downloaded extension size {actual_len} does not match content length {content_length}");
}
}
let decompressed_bytes = GzipDecoder::new(BufReader::new(tgz_bytes.as_slice()));
// let decompressed_bytes = GzipDecoder::new(BufReader::new(tgz_bytes));
let archive = Archive::new(decompressed_bytes); let archive = Archive::new(decompressed_bytes);
archive.unpack(extension_dir).await?; archive.unpack(extension_dir).await?;
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {