{"record":{"id":"8ad53328e1d7998e","repo":"jdx/mise","slug":"malformed-fat-arch-in","errorCode":null,"errorMessage":"malformed fat arch in {}","messagePattern":"malformed fat arch in (.+?)","errorType":"exception","errorClass":"eyre::Report","httpStatus":null,"severity":"error","filePath":"src/system/packages/brew/macho.rs","lineNumber":193,"sourceCode":"        return Ok(false);\n    }\n    let be_magic = u32::from_be_bytes(content[..4].try_into().unwrap());\n    if be_magic == FAT_MAGIC_BE {\n        let nfat = u32::from_be_bytes(content[4..8].try_into().unwrap()) as usize;\n        let mut changed = false;\n        // collect slice ranges first (fat headers are big-endian)\n        let mut ranges = vec![];\n        for i in 0..nfat {\n            let entry = 8 + i * 20;\n            if entry + 20 > content.len() {\n                bail!(\"malformed fat header in {}\", path.display());\n            }\n            let offset =\n                u32::from_be_bytes(content[entry + 8..entry + 12].try_into().unwrap()) as usize;\n            let size =\n                u32::from_be_bytes(content[entry + 12..entry + 16].try_into().unwrap()) as usize;\n            if offset + size > content.len() {\n                bail!(\"malformed fat arch in {}\", path.display());\n            }\n            ranges.push(offset..offset + size);\n        }\n        for range in ranges {\n            changed |= patch_slice(&mut content[range], replacements, path)?;\n        }\n        Ok(changed)\n    } else {\n        patch_slice(content, replacements, path)\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use crate::system::packages::brew::relocate::tests::test_replacements;\n\n    /// build a minimal 64-bit Mach-O: header + LC_SEGMENT_64 (one section)","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/packages/brew/macho.rs#L175-L211","documentation":"Within a fat Mach-O, each arch entry carries an offset and size delimiting its slice. An entry whose offset+size exceeds the file length describes data that does not exist, so the slicer refuses to patch rather than index out of bounds or patch the wrong bytes.","triggerScenarios":"patch_macho fat path: offset + size > content.len() for some arch entry. Produced by truncated files (slices at the end missing), corrupted arch tables, or files with stale headers after being truncated/re-padded.","commonSituations":"Partially downloaded universal bottles; artifacts damaged in transit; fat binaries post-processed by tools that stripped slices without updating the header.","solutions":["Re-download the bottle from scratch and retry the pour","Verify with lipo -detailed_info — slices outside the file will fail there too","Report upstream if the artifact is reproducibly valid in other tooling"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Every fat-arch slice must lie inside the file before patching.\nfn fat_slices_in_bounds(content: &[u8]) -> bool {\n    if content.len() < 8 { return false; }\n    let nfat = u32::from_be_bytes(content[4..8].try_into().unwrap()) as usize;\n    (0..nfat).all(|i| {\n        let e = 8 + i * 20;\n        e + 20 <= content.len() && {\n            let off = u32::from_be_bytes(content[e + 8..e + 12].try_into().unwrap()) as usize;\n            let size = u32::from_be_bytes(content[e + 12..e + 16].try_into().unwrap()) as usize;\n            off.checked_add(size).is_some_and(|end| end <= content.len())\n        }\n    })\n}","typeGuard":"fn fat_macho_wellformed(content: &[u8]) -> bool {\n    fat_header_ok(content) && fat_slices_in_bounds(content)\n}","tryCatchPattern":"match patch_macho(&mut content, &replacements, &path) {\n    Ok(changed) => changed,\n    Err(e) => { warn!(\"{}: {e:#}\", path.display()); false }\n}","preventionTips":["Re-download bottles whose size differs from the manifest instead of patching them","Validate universal binaries with lipo -detailed_info before automated relocation"],"tags":["brew","macho","macos","fat-binary","validation"],"backgroundTag":"mach-o-header-validation-failed","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}