Repository: alexcrichton/tar-rs (language: rust)

Issue:
panicked at 'attempt to add with overflow'
For given input file:

[in.zip](https://github.com/alexcrichton/tar-rs/files/7274779/in.zip)
with following code:

```rust
fn main() {
    let filepath = "<input file>"
    let data = std::fs::read(filepath).unwrap();

    parse_tar(&data);
    
}

pub fn parse_tar(data: &[u8]) {
    use std::io::Cursor;

    let cursor = Cursor::new(data);
    let mut archive = tar::Archive::new(cursor);
    let entries = match archive.entries() {
        Ok(entries) => entries,
        Err(..) => return,
    };
    for entry in entries {
        if let Ok(mut entry) = entry {
            let _ = entry.path();
            let _ = entry.path_bytes();
            let _ = entry.link_name();
            let _ = entry.link_name_bytes();
            if let Ok(Some(mut extensions)) = entry.pax_extensions() {
                while let Some(Ok(extension)) = extensions.next() {
                    let _ = extension.key();
                    let _ = extension.key_bytes();
                    let _ = extension.value();
                    let _ = extension.value_bytes();
                }
            }
            let _ = entry.header().as_old();
            let _ = entry.header().as_ustar();
            let _ = entry.header().as_gnu();
            let _ = entry.header().as_bytes();
            let _ = entry.header().entry_size();
            let _ = entry.header().size();
            let _ = entry.header().path();
            let _ = entry.header().path_bytes();
            let _ = entry.header().link_name();
            let _ = entry.header().link_name_bytes();
            let _ = entry.header().mode();
            let _ = entry.header().uid();
            let _ = entry.header().gid();
            let _ = entry.header().mtime();
            let _ = entry.header().username();
            let _ = entry.header().username_bytes();
            let _ = entry.header().groupname();
            let _ = entry.header().groupname_bytes();
            let _ = entry.header().device_major();
            let _ = entry.header().device_minor();
            let _ = entry.header().entry_type();
            let _ = entry.header().cksum();
        }
    }
}
```

it has output:
```
thread 'main' panicked at 'attempt to add with overflow', /home/szx5097/.cargo/registry/src/github.com-1ecc6299db9ec823/tar-0.4.37/src/archive.rs:301:20
stack backtrace:
   0: rust_begin_unwind
   1: core::panicking::panic_fmt
   2: core::panicking::panic
   3: tar::archive::EntriesFields::next_entry_raw
             at /home/szx5097/.cargo/registry/src/github.com-1ecc6299db9ec823/tar-0.4.37/src/archive.rs:301:20
   4: tar::archive::EntriesFields::next_entry
             at /home/szx5097/.cargo/registry/src/github.com-1ecc6299db9ec823/tar-0.4.37/src/archive.rs:319:31
   5: <tar::archive::EntriesFields as core::iter::traits::iterator::Iterator>::next
             at /home/szx5097/.cargo/registry/src/github.com-1ecc6299db9ec823/tar-0.4.37/src/archive.rs:488:19
   6: <tar::archive::Entries<R> as core::iter::traits::iterator::Iterator>::next
             at /home/szx5097/.cargo/registry/src/github.com-1ecc6299db9ec823/tar-0.4.37/src/archive.rs:228:9
...
```




Discussion / hints:
The input file is the file in the zip file, not zip file itself :)

Fix patch:
diff --git a/src/archive.rs b/src/archive.rs
index 8c333322..4a8f3379 100644
--- a/src/archive.rs
+++ b/src/archive.rs
@@ -298,8 +298,10 @@ impl<'a> EntriesFields<'a> {
 
         // Store where the next entry is, rounding up by 512 bytes (the size of
         // a header);
-        let size = (size + 511) & !(512 - 1);
-        self.next += size;
+        let size = size
+            .checked_add(511)
+            .ok_or_else(|| other("size overflow"))?;
+        self.next += size & !(512 - 1);
 
         Ok(Some(ret.into_entry()))
     }


Test patch:
diff --git a/tests/all.rs b/tests/all.rs
index d29a5190..1fbb770b 100644
--- a/tests/all.rs
+++ b/tests/all.rs
@@ -1245,3 +1245,16 @@ fn tar_directory_containing_special_files() {
     t!(ar.append_path("null"));
     t!(ar.finish());
 }
+
+#[test]
+fn header_size_overflow() {
+    let mut ar = Builder::new(Vec::new());
+    let mut header = Header::new_gnu();
+    header.set_size(0xffffffffffffffff);
+    header.set_cksum();
+    ar.append(&mut header, "x".as_bytes()).unwrap();
+    let result = t!(ar.into_inner());
+    let mut ar = Archive::new(&result[..]);
+    let mut e = ar.entries().unwrap();
+    assert!(e.next().unwrap().is_err());
+}