tonhowtf/omniget · error

PNG truncado

Error message

PNG truncado

What it means

strip_png scans PNG chunks to drop metadata (e.g. text/eXIf chunks) while keeping image data. Before copying a chunk it computes end = i + 12 + len; if that exceeds the buffer length the PNG is truncated mid-chunk, so the function refuses to proceed rather than emit a corrupt file.

Solutions

  1. Re-download or re-obtain the PNG file; the source bytes are incomplete
  2. Validate the PNG (e.g. ends with an IEND chunk) before calling strip_bytes
  3. Wrap the call and fall back to serving/keeping the original bytes if stripping fails

Example fix

// before
let cleaned = strip_bytes(&raw)?;
// after
let cleaned = match strip_bytes(&raw) {
    Ok(c) => c,
    Err(_) => raw.to_vec(), // keep original on truncation
};
Defensive patterns

Strategy: try-catch

Validate before calling

// rust
fn png_looks_complete(data: &[u8]) -> bool {
    data.len() >= 12 && data.ends_with(b"IEND")
}

Try / catch

match exif::strip_bytes(&data) {
    Ok(clean) => clean,
    Err(e) if e.to_string().contains("PNG truncado") => data.to_vec(), // keep original
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling strip_bytes with PNG data whose chunk length field points past the end of the buffer — i.e. the last chunk is incomplete or the length bytes are corrupt.

Common situations: Processing partially downloaded images, files cut off mid-transfer, or truncated attachments; also corrupted PNGs with bogus chunk length fields.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/3c6dc4d5a68799c8. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/tools/exif.rs:248

    }
    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;
    while i + 8 <= data.len() {
        let fourcc: [u8; 4] = [data[i], data[i + 1], data[i + 2], data[i + 3]];

View on GitHub (pinned to 8600b91f42)