tlc: Sprint 3 C15 — TarVfs::open rejects empty/garbage archives

The tar crate returns an empty iterator (without erroring) for
both zero-byte files and files that aren't valid tar archives.
TarVfs::open() previously succeeded in both cases, producing an
'unbrowsable' archive the user couldn't navigate.

Fix:
  TarVfs::open() now checks entries.is_empty() after list() and
  returns VfsError::Other('empty tar archive') when empty. This
  covers both truly empty files (corrupt/truncated) and garbage
  bytes (e.g., text mistakenly saved with .tar extension).

Tests (2 new in vfs::tar::tests):
  - tar_vfs_open_empty_file_errors
  - tar_vfs_open_garbage_bytes_errors

Total: 1281 passing (was 1279; +2 new).
This commit is contained in:
kellito
2026-07-05 19:14:30 +03:00
parent 08dbaf519a
commit 1826f079d3
@@ -119,6 +119,13 @@ impl TarVfs {
kinds: HashMap::new(),
};
me.list()?;
// An empty tar (zero entries) usually indicates a corrupt or
// truncated archive; the tar crate returns an empty
// iterator without erroring. Surface this as a real error
// so the caller doesn't present an unbrowsable archive.
if me.entries.is_empty() {
return Err(VfsError::Other("empty tar archive".to_string()));
}
Ok(me)
}
@@ -449,6 +456,29 @@ mod tests {
assert!(r.is_err());
}
#[test]
fn tar_vfs_open_empty_file_errors() {
// An empty file is not a valid tar archive; opening must
// return an error rather than silently producing an empty
// (unbrowsable) archive.
let p = std::env::temp_dir().join("tlc-tar-empty.tar");
std::fs::write(&p, b"").unwrap();
let r = TarVfs::open(p.clone());
assert!(r.is_err(), "empty file must error on TarVfs::open");
let _ = std::fs::remove_file(&p);
}
#[test]
fn tar_vfs_open_garbage_bytes_errors() {
// Random bytes that aren't a valid tar header must error
// rather than be silently accepted.
let p = std::env::temp_dir().join("tlc-tar-garbage.tar");
std::fs::write(&p, b"not a tar archive at all, just text").unwrap();
let r = TarVfs::open(p.clone());
assert!(r.is_err(), "garbage bytes must error on TarVfs::open");
let _ = std::fs::remove_file(&p);
}
#[test]
fn tar_vfs_extract_gz_round_trip() {
let dir = std::env::temp_dir().join("tlc-tar-gz-test");