{"record":{"id":"3c6dc4d5a68799c8","repo":"tonhowtf/omniget","slug":"png-truncado","errorCode":null,"errorMessage":"PNG truncado","messagePattern":"PNG truncado","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src-tauri/omniget-core/src/core/tools/exif.rs","lineNumber":248,"sourceCode":"    }\n    Ok(out)\n}\n\nconst PNG_DROP: &[&[u8; 4]] = &[b\"tEXt\", b\"zTXt\", b\"iTXt\", b\"eXIf\", b\"tIME\", b\"dSIG\"];\n\nfn strip_png(data: &[u8]) -> anyhow::Result<Vec<u8>> {\n    let mut out = Vec::with_capacity(data.len());\n    out.extend_from_slice(&data[0..8]);\n    let mut i = 8usize;\n    while i + 8 <= data.len() {\n        let len = u32::from_be_bytes([data[i], data[i + 1], data[i + 2], data[i + 3]]) as usize;\n        let ctype: [u8; 4] = [data[i + 4], data[i + 5], data[i + 6], data[i + 7]];\n        let end = i\n            .checked_add(12)\n            .and_then(|v| v.checked_add(len))\n            .ok_or_else(|| anyhow!(\"PNG com tamanho de chunk inválido\"))?;\n        if end > data.len() {\n            return Err(anyhow!(\"PNG truncado\"));\n        }\n        if !PNG_DROP.iter().any(|d| d.as_slice() == ctype) {\n            out.extend_from_slice(&data[i..end]);\n        }\n        i = end;\n        if &ctype == b\"IEND\" {\n            break;\n        }\n    }\n    Ok(out)\n}\n\nfn strip_webp(data: &[u8]) -> anyhow::Result<Vec<u8>> {\n    let mut body: Vec<u8> = Vec::with_capacity(data.len());\n    body.extend_from_slice(b\"WEBP\");\n    let mut i = 12usize;\n    while i + 8 <= data.len() {\n        let fourcc: [u8; 4] = [data[i], data[i + 1], data[i + 2], data[i + 3]];","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/tonhowtf/omniget/blob/8600b91f4246848bac346874daa9e61c1fc5677a/src-tauri/omniget-core/src/core/tools/exif.rs#L230-L266","documentation":"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.","triggerScenarios":"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.","commonSituations":"Processing partially downloaded images, files cut off mid-transfer, or truncated attachments; also corrupted PNGs with bogus chunk length fields.","solutions":["Re-download or re-obtain the PNG file; the source bytes are incomplete","Validate the PNG (e.g. ends with an IEND chunk) before calling strip_bytes","Wrap the call and fall back to serving/keeping the original bytes if stripping fails"],"exampleFix":"// before\nlet cleaned = strip_bytes(&raw)?;\n// after\nlet cleaned = match strip_bytes(&raw) {\n    Ok(c) => c,\n    Err(_) => raw.to_vec(), // keep original on truncation\n};","handlingStrategy":"try-catch","validationCode":"// rust\nfn png_looks_complete(data: &[u8]) -> bool {\n    data.len() >= 12 && data.ends_with(b\"IEND\")\n}","typeGuard":null,"tryCatchPattern":"match exif::strip_bytes(&data) {\n    Ok(clean) => clean,\n    Err(e) if e.to_string().contains(\"PNG truncado\") => data.to_vec(), // keep original\n    Err(e) => return Err(e),\n}","preventionTips":["Verify downloads complete (size/checksum) before post-processing","Check the file ends with an IEND chunk before stripping","Treat stripping as optional — fall back to original bytes on failure"],"tags":["png","truncated-file","exif-stripping"],"backgroundTag":"file-read-failed","analyzedSha":"8600b91f4246848bac346874daa9e61c1fc5677a","analyzedAt":"2026-09-12T14:29:19.317Z","contentChangedAt":"2026-09-12T14:29:19.317Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}