{"id":"606387cc14a2d854","repo":"rust-lang/rust","slug":"archive-member-at-offset-start-with-size-exce","errorCode":null,"errorMessage":"archive member at offset {start} with size {} exceeds archive size {} in `{}`","messagePattern":"archive member at offset (.+?) with size (.+?) exceeds archive size (.+?) in `(.+?)`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler/rustc_codegen_ssa/src/back/archive.rs","lineNumber":623,"sourceCode":"            }\n            Some((names, rename_suffix))\n        } else {\n            None\n        };\n\n        let mut entries = Vec::new();\n\n        for (entry_name, entry) in self.entries {\n            let data: Box<dyn AsRef<[u8]>> = match entry.source {\n                ArchiveEntrySource::Archive { archive_index, file_range } => {\n                    let src_archive = &self.src_archives[archive_index];\n                    let archive_data = &src_archive.1;\n                    let start = file_range.0 as usize;\n                    let end = start + file_range.1 as usize;\n                    let Some(data) = archive_data.get(start..end) else {\n                        return Err(io_error_context(\n                            \"invalid archive member\",\n                            io::Error::new(\n                                io::ErrorKind::InvalidData,\n                                format!(\n                                    \"archive member at offset {start} with size {} \\\n                                         exceeds archive size {} in `{}`\",\n                                    file_range.1,\n                                    archive_data.len(),\n                                    src_archive.0.display(),\n                                ),\n                            ),\n                        ));\n                    };\n\n                    if entry.kind == ArchiveEntryKind::RustObj\n                        && let Some(sym) = &symbols\n                    {\n                        Box::new(apply_edits(data, &sym.exported, sym.hide, rename.as_ref()))\n                    } else {\n                        Box::new(data)","sourceCodeStart":605,"sourceCodeEnd":641,"githubUrl":"https://github.com/rust-lang/rust/blob/22057b88b091743bc0fd8d592a9264f0a6951403/compiler/rustc_codegen_ssa/src/back/archive.rs#L605-L641","documentation":"Returned while copying an entry out of a source archive during output archive assembly: the entry's recorded (offset, size) file_range extends past the end of the memory-mapped source archive bytes. The slice .get(start..end) returns None, so rustc builds an InvalidData io::Error (wrapped by io_error_context) describing the exact offset, member size, total archive size, and archive path. It indicates a corrupt, truncated, or inconsistently-indexed input .a/.rlib.","triggerScenarios":"Triggered by ArchiveBuilder::write when iterating self.entries and an ArchiveEntrySource::Archive entry references a file_range that lies outside the mapped src_archive. Happens if an input rlib/static archive's header table disagrees with its actual byte length.","commonSituations":"A truncated or partially-written .rlib left behind by a killed/interrupted previous build. Disk corruption or a bad network filesystem serving the build cache. A malformed third-party .a static library with an ar index pointing past EOF. Concurrent writes to the same archive by two rustc invocations.","solutions":["Run cargo clean (or remove target/) to delete the suspect archive and rebuild from source.","Inspect the named archive with `ar t <path>` / `llvm-ar t <path>` to confirm it is malformed; if so, delete it.","If the archive came from a crate dependency or vendored source, re-fetch/re-vendor it (rm -rf of the cached copy) to rule out a truncated download.","Ensure no two build processes or editors are writing to the same target directory concurrently."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"use std::fs::File;\nuse std::io::{Read, Seek, SeekFrom};\n\nfn archive_members_in_bounds(path: &std::path::Path) -> std::io::Result<bool> {\n    let mut f = File::open(path)?;\n    let total = f.metadata()?.len();\n    let mut sig = [0u8; 8];\n    if f.read_exact(&mut sig).is_err() || &sig != b\"!<arch>\\n\" {\n        return Ok(false);\n    }\n    loop {\n        let mut hdr = [0u8; 60];\n        if f.read_exact(&mut hdr).is_err() { break; }\n        let size_field = std::str::from_utf8(&hdr[48..58])\n            .unwrap_or(\"0\").trim().parse::<u64>().unwrap_or(0);\n        let start = f.stream_position()?;\n        if start.saturating_add(size_field) > total { return Ok(false); }\n        let advance = (size_field + 1) & !1; // 2-byte align\n        f.seek(SeekFrom::Current(advance as i64))?;\n    }\n    Ok(true)\n}\n\n// caller: assert!(archive_members_in_bounds(Path::new(\"libfoo.a\"))?);","typeGuard":"fn is_well_formed_archive(path: &std::path::Path) -> bool {\n    archive_members_in_bounds(path).unwrap_or(false)\n}","tryCatchPattern":"let s = String::from_utf8_lossy(&output.stderr);\nif s.contains(\"exceeds archive size\") {\n    eprintln!(\"archive {} is corrupt; rebuilding\", path.display());\n    rebuild_archive(path)?;\n}","preventionTips":["Sanity-check every `.a`/`.rlib` with `ar t libfoo.a` (or the validator above) before linking.","Treat a failed `ar t` as fatal; do not retry the link against the same file.","Rebuild archives from objects rather than copying them across filesystems with truncation risk."],"tags":["archive","rlib","io","corruption","ar"],"analyzedSha":"22057b88b091743bc0fd8d592a9264f0a6951403","analyzedAt":"2026-08-03T08:09:25.915Z","schemaVersion":2}