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");