Reject ZIP entries with inconsistent decoded sizes

Found while testing crates/geocode/src/unzip.rs:64

Co-Authored-By: GPT-6-Luna <noreply@openai.com>
This commit is contained in:
Max Mittelstädt
2026-10-28 16:41:59 +00:00
co-authored by GPT-6-Luna
parent e381c1ae6b
commit 7ab2575505
+18 -1
View File
@@ -61,7 +61,13 @@ pub fn extract(zip: &[u8], name: &str, max: usize) -> Result<Vec<u8>, GeocodeErr
return match method {
0 if data.len() <= max => Ok(data.to_vec()),
0 => Err(GeocodeError::Invalid(format!("{name} is larger than {max} bytes"))),
8 => miniz_oxide::inflate::decompress_to_vec_with_limit(data, max).map_err(|e| bad(&format!("deflate: {e:?}"))),
8 => {
let decoded = miniz_oxide::inflate::decompress_to_vec_with_limit(data, max).map_err(|e| bad(&format!("deflate: {e:?}")))?;
if decoded.len() != usize_ {
return Err(bad("uncompressed size"));
}
Ok(decoded)
}
m => Err(bad(&format!("compression method {m}"))),
};
}
@@ -120,4 +126,15 @@ mod tests {
let _ = extract(&bad, "cities15000.txt", 100);
}
}
#[test]
fn rejects_deflated_entry_with_inconsistent_directory_size() {
let mut z = make("cities15000.txt", b"hello world");
let eocd = z.len() - 22;
let cd = u32::from_le_bytes([z[eocd + 16], z[eocd + 17], z[eocd + 18], z[eocd + 19]]) as usize;
let declared_size = cd + 24;
z[declared_size..declared_size + 4].copy_from_slice(&2u32.to_le_bytes());
assert!(extract(&z, "cities15000.txt", 100).is_err());
}
}