GitoxideLabs/gitoxide · error
pack entry header overflowed
Error message
pack entry header overflowed
What it means
While streaming-parsing a pack entry header, each continuation byte contributes 7 bits shifted left; if the shift exceeds 63 bits the `checked_shl` overflows and an InvalidData io::Error 'pack entry header overflowed' is returned. It means the multi-byte size header is implausibly long for a valid pack.
Solutions
- Verify the pack file integrity (`gix pack verify` / `git fsck`)
- Re-download or re-clone to replace the corrupt pack
- Confirm the source stream is an authentic git pack file
- During fuzzing/tests, treat this as correct rejection of invalid input
Defensive patterns
Strategy: try-catch
Validate before calling
// checksum the pack before parsing assert_eq!(pack.trailer(), expected_sha);
Try / catch
match parse_result {
Err(e) if e.to_string().contains("pack entry header overflowed") => {
// reject pack as corrupt, re-fetch
}
other => other?,
} Prevention
- Verify pack SHA-1 trailer before decoding entries
- Avoid parsing partial pack downloads
- Fuzz-test parsers expecting clean rejection
When it happens
Trigger: Calling `data::Entry::from_read` (via streaming_parse_header_info) on a stream whose header has so many continuation bytes that the u64 shift would overflow — i.e. a corrupt or malicious header.
Common situations: Corrupted pack downloads, adversarial pack files, fuzzing inputs.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- entry header size does not fit into u16
- Only human format is supported right now
- Integer overflow
- ran out of bytes before reading desired amount of bytes
- integer out of range
AI-assisted analysis of GitoxideLabs/gitoxide@e73179060b (2026-09-08).
Data as JSON: /api/errors/cddc9310c883e501.
Report an issue: GitHub.
Appendix: source
Thrown at gix-pack/src/data/entry/decode.rs:127
})
}
#[inline]
fn streaming_parse_header_info(read: &mut dyn io::Read) -> Result<(u8, u64, usize), io::Error> {
let mut byte = [0u8; 1];
read.read_exact(&mut byte)?;
let mut c = byte[0];
let mut i = 1;
let type_id = (c >> 4) & 0b0000_0111;
let mut size = u64::from(c) & 0b0000_1111;
let mut shift = 4u32;
while c & 0b1000_0000 != 0 {
read.read_exact(&mut byte)?;
c = byte[0];
i += 1;
let component = u64::from(c & 0b0111_1111)
.checked_shl(shift)
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "pack entry header overflowed"))?;
size = size
.checked_add(component)
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "pack entry header overflowed"))?;
shift += 7;
}
Ok((type_id, size, i))
}
/// Parses the header of a pack-entry, yielding object type id, decompressed object size, and consumed bytes
#[inline]
fn parse_header_info(data: &[u8]) -> Result<(u8, u64, usize), Error> {
let mut c = *data.first().ok_or(Error::Corrupt {
message: "need a pack entry header, got empty input",
})?;
let mut i = 1;
let type_id = (c >> 4) & 0b0000_0111;
let mut size = u64::from(c) & 0b0000_1111;
let mut shift = 4u32;View on GitHub (pinned to e73179060b)