bakery: a failed data-archive download must not abort the whole install
`fetch_verify_write` treats a download/checksum failure as a soft warning and returns Ok without writing — but the `NamedTempFile` is already created (0 bytes). Gating extraction on `exists()` let the empty file reach `tar tvf`, which bailed with a misleading "not in gzip format" and aborted the install. Gate on non-empty instead.
This commit is contained in:
parent
2897335016
commit
2affeabce0
1 changed files with 39 additions and 2 deletions
|
|
@ -523,8 +523,17 @@ fn fetch_extract_archive(
|
||||||
.into_temp_path();
|
.into_temp_path();
|
||||||
|
|
||||||
fetch_verify_write(pkg, filename, sha256, &tmp_archive, "data archive")?;
|
fetch_verify_write(pkg, filename, sha256, &tmp_archive, "data archive")?;
|
||||||
if !tmp_archive.exists() {
|
// `fetch_verify_write` treats a download/checksum/missing-sha failure
|
||||||
// fetch_verify_write already warned (download/checksum failure).
|
// as a soft warning and returns `Ok` *without writing* — but the
|
||||||
|
// `NamedTempFile` above is already created (0 bytes), so gating on
|
||||||
|
// mere `exists()` would let an empty file through to `tar tvf`, which
|
||||||
|
// then bails with a confusing "not in gzip format" error that masks
|
||||||
|
// the real cause and aborts the whole install. Gate on *non-empty*.
|
||||||
|
if std::fs::metadata(&tmp_archive)
|
||||||
|
.map(|m| m.len())
|
||||||
|
.unwrap_or(0)
|
||||||
|
== 0
|
||||||
|
{
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1036,6 +1045,34 @@ mod tests {
|
||||||
assert!(err.to_string().contains("unsafe path"));
|
assert!(err.to_string().contains("unsafe path"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn fetch_extract_archive_download_failure_is_non_fatal() {
|
||||||
|
// A checksum mismatch makes `fetch_verify_write` warn-and-return
|
||||||
|
// Ok without writing, leaving the (already created) NamedTempFile
|
||||||
|
// empty. The pre-extraction `tar tvf` must be skipped for an empty
|
||||||
|
// file rather than bailing, so a failed archive download degrades
|
||||||
|
// gracefully and does NOT abort the package install (regression
|
||||||
|
// for the empty-temp-file bug).
|
||||||
|
let base_url = serve_once(b"definitely not a tar.gz");
|
||||||
|
let pkg = test_package(&base_url);
|
||||||
|
|
||||||
|
let dest_dir = tempdir().unwrap();
|
||||||
|
let res = fetch_extract_archive(
|
||||||
|
&pkg,
|
||||||
|
"content.tar.gz",
|
||||||
|
&Some("0".repeat(64)), // will not match the served bytes
|
||||||
|
dest_dir.path(),
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
res.is_ok(),
|
||||||
|
"a data-archive download/checksum failure must be non-fatal"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
std::fs::read_dir(dest_dir.path()).unwrap().next().is_none(),
|
||||||
|
"nothing should be extracted into dest_dir"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ensure_safe_component_accepts_plain_names() {
|
fn ensure_safe_component_accepts_plain_names() {
|
||||||
assert!(ensure_safe_component("breadhelp", "x").is_ok());
|
assert!(ensure_safe_component("breadhelp", "x").is_ok());
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue