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

  1. Validate the file is a real PNG (8-byte signature and sane IHDR) before calling strip_bytes
  2. Treat the input as corrupted and skip metadata stripping for this file
  3. Sanity-check the first chunk length (should be 13 for IHDR) before parsing
  4. 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

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


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)