From 1826f079d38ac7d4f74155677a8f66300780b8b0 Mon Sep 17 00:00:00 2001 From: kellito Date: Sun, 5 Jul 2026 19:14:30 +0300 Subject: [PATCH] =?UTF-8?q?tlc:=20Sprint=203=20C15=20=E2=80=94=20TarVfs::o?= =?UTF-8?q?pen=20rejects=20empty/garbage=20archives?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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). --- local/recipes/tui/tlc/source/src/vfs/tar.rs | 30 +++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/local/recipes/tui/tlc/source/src/vfs/tar.rs b/local/recipes/tui/tlc/source/src/vfs/tar.rs index 849a2c51f5..54bffd5324 100644 --- a/local/recipes/tui/tlc/source/src/vfs/tar.rs +++ b/local/recipes/tui/tlc/source/src/vfs/tar.rs @@ -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");