tonhowtf/omniget · error
PNG com tamanho de chunk inválido
Error message
PNG com tamanho de chunk inválido
What it means
strip_png walks PNG chunks after the 8-byte signature, reading each chunk's length (4 bytes BE) and type (4 bytes), where each chunk spans 12 + len bytes total. It uses checked arithmetic and throws this error if the chunk size computation overflows (i + 12 + len exceeds usize).
Solutions
- Validate the file is a real PNG (8-byte signature and sane IHDR) before calling strip_bytes
- Treat the input as corrupted and skip metadata stripping for this file
- Sanity-check the first chunk length (should be 13 for IHDR) before parsing
- Regenerate or re-encode the source image if it is corrupted
Example fix
// before
let cleaned = exif::strip_bytes(&data).unwrap_or(data);
// after
let is_png = data.starts_with(b"\x89PNG\r\n\x1a\n");
let cleaned = if is_png {
exif::strip_bytes(&data).unwrap_or_else(|_| data.clone())
} else { data }; Defensive patterns
Strategy: try-catch
Validate before calling
fn looks_like_png(data: &[u8]) -> bool {
data.len() >= 33 && data.starts_with(b"\x89PNG\r\n\x1a\n")
&& u32::from_be_bytes([data[8+8], data[8+9], data[8+10], data[8+11]]) <= data.len() as u32
} Type guard
fn is_safe_png(data: &[u8]) -> bool {
data.starts_with(b"\x89PNG\r\n\x1a\n") && data.len() >= 8
} Try / catch
let out = match exif::strip_bytes(&data) {
Ok(clean) => clean,
Err(e) if e.to_string().contains("PNG") => {
warn!("imagem PNG corrompida, mantendo original: {e}");
data
}
Err(e) => return Err(e),
}; Prevention
- Verify the PNG signature before running the metadata stripper
- Fall back to the original bytes when stripping fails — stripping is best-effort
- Treat untrusted images defensively; corrupted length fields indicate malformed input
When it happens
Trigger: Calling strip_bytes()/strip_png() on data whose PNG chunk length field is corrupt/huge such that 12 + len overflows usize — i.e. malformed or non-PNG data that happens to be passed to the PNG stripper.
Common situations: Processing a corrupted/truncated PNG with garbage length bytes; feeding a JPEG or other file mistakenly identified as PNG; fuzzed or maliciously crafted images where the length field is 0xFFFFFFFF or similar.
Related errors
- ffmpeg metadata failed
- JPEG sem cabecalho SOF
- máscara com tamanho inconsistente
- não consegui medir a duração do vídeo
- não gravei o PNG
AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12).
Data as JSON: /api/errors/d844029a250a025c.
Report an issue: GitHub.
Appendix: source
Thrown at src-tauri/omniget-core/src/core/tools/exif.rs:246
}
i = end;
}
Ok(out)
}
const PNG_DROP: &[&[u8; 4]] = &[b"tEXt", b"zTXt", b"iTXt", b"eXIf", b"tIME", b"dSIG"];
fn strip_png(data: &[u8]) -> anyhow::Result<Vec<u8>> {
let mut out = Vec::with_capacity(data.len());
out.extend_from_slice(&data[0..8]);
let mut i = 8usize;
while i + 8 <= data.len() {
let len = u32::from_be_bytes([data[i], data[i + 1], data[i + 2], data[i + 3]]) as usize;
let ctype: [u8; 4] = [data[i + 4], data[i + 5], data[i + 6], data[i + 7]];
let end = i
.checked_add(12)
.and_then(|v| v.checked_add(len))
.ok_or_else(|| anyhow!("PNG com tamanho de chunk inválido"))?;
if end > data.len() {
return Err(anyhow!("PNG truncado"));
}
if !PNG_DROP.iter().any(|d| d.as_slice() == ctype) {
out.extend_from_slice(&data[i..end]);
}
i = end;
if &ctype == b"IEND" {
break;
}
}
Ok(out)
}
fn strip_webp(data: &[u8]) -> anyhow::Result<Vec<u8>> {
let mut body: Vec<u8> = Vec::with_capacity(data.len());
body.extend_from_slice(b"WEBP");
let mut i = 12usize;View on GitHub (pinned to 8600b91f42)