{"record":{"id":"f7baf9b1d3771c95","repo":"unionlabs/union","slug":"parsing-rev","errorCode":null,"errorMessage":"parsing rev","messagePattern":"parsing rev","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/embed-commit/verifier/src/lib.rs","lineNumber":38,"sourceCode":"///\n/// This function will error if the elf binary bytes provided cannot be parsed, or if the embedded git rev cannot be parsed. If there is no embedded git rev then `Ok(None)` will be returned.\npub fn extract_elf(bz: &[u8]) -> Result<Option<Rev>> {\n    let file = ElfBytes::<AnyEndian>::minimal_parse(bz).context(\"parsing elf file\")?;\n\n    let Some(section) = file\n        .section_header_by_name(\".note.embed_commit.GIT_REV\")\n        .context(\"reading GIT_REV note section\")?\n    else {\n        return Ok(None);\n    };\n\n    let (bytes, _) = file\n        .section_data(&section)\n        .context(\"reading GIT_REV note section data\")?;\n\n    bytemuck::checked::try_from_bytes::<Rev>(&bytes[0..std::mem::size_of::<Rev>()])\n        .map_err(|e| anyhow!(e.to_string()))\n        .context(\"parsing rev\")\n        .map(|rev| Some(*rev))\n}\n\n/// Retrieve the git rev from the provided wasm binary bytes.\n///\n/// # Errors\n///\n/// This function will error if the wasm binary bytes provided cannot be parsed, or if the returned git rev cannot be parsed. If there is no `commit_hash` export then `Ok(None)` will be returned.\npub fn extract_wasm(bz: &[u8]) -> Result<Option<Rev>> {\n    let engine = Engine::default();\n    let module = Module::from_binary(&engine, bz)?;\n    let mut linker = Linker::new(&engine);\n    let mut store: Store<()> = Store::new(&engine, ());\n\n    // stub all imports as they're unused when evaluating commit_hash\n    for import in module.imports() {\n        linker.func_new(\n            import.module(),","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/unionlabs/union/blob/031785bb6dc6b957c624e62bc64c184409c97d7b/lib/embed-commit/verifier/src/lib.rs#L20-L56","documentation":"extract_elf reads the .note.embed_commit.GIT_REV ELF section and reinterprets its first size_of::<Rev>() (32) bytes as the Rev enum (discriminant for unknown/dirty plus a 20-byte hash). bytemuck's checked cast fails when those bytes are not a valid Rev bit pattern — typically an unknown discriminant byte — and the anyhow context \"parsing rev\" wraps the failure.","triggerScenarios":"Verifying an ELF whose GIT_REV note section exists but was written by a different producer/version or is corrupted: an invalid tag byte, a section produced with a different Rev layout, or bytes garbled by post-build processing. (A section shorter than 32 bytes instead panics at slicing before reaching this error.)","commonSituations":"Binaries rebuilt or patched after the note was embedded; a different toolchain writing a same-named section; embed-commit version drift between the builder that embedded the note and the verifier parsing it.","solutions":["Rebuild the artifact with the union embed-commit toolchain so the note is well-formed","Confirm you are inspecting the intended binary and inspect the section: readelf -x .note.embed_commit.GIT_REV <file>","Align the verifier's embed-commit crate version with the producer's","Treat parse failure as 'unrecognized producer' and report the underlying PodCastError rather than retrying"],"exampleFix":"// before\nbytemuck::checked::try_from_bytes::<Rev>(&bytes[0..std::mem::size_of::<Rev>()])\n  .map_err(|e| anyhow!(e.to_string()))\n  .context(\"parsing rev\")\n\n// after — distinguish truncation from an invalid bit pattern\nlet need = std::mem::size_of::<Rev>();\nif bytes.len() < need {\n  anyhow::bail!(\"GIT_REV note too short: {} < {need}; binary not built by embed-commit\", bytes.len());\n}\nlet rev = bytemuck::checked::try_from_bytes::<Rev>(&bytes[..need])\n  .map_err(|e| anyhow!(\"invalid GIT_REV bit pattern ({e:?}); binary not built by embed-commit\"))?\n  .clone();","handlingStrategy":"validation","validationCode":"// Validate the note before the checked cast\nlet need = std::mem::size_of::<Rev>();\nif bytes.len() < need { /* too short: not an embed-commit ELF */ }\nlet tag = bytes[0]; // discriminant byte for the repr(u8) Rev layout\nif tag > 2 { /* invalid discriminant: foreign or corrupted producer */ }","typeGuard":"fn as_rev(bytes: &[u8]) -> Option<Rev> {\n    if bytes.len() < std::mem::size_of::<Rev>() {\n        return None;\n    }\n    bytemuck::checked::try_from_bytes::<Rev>(&bytes[..std::mem::size_of::<Rev>()])\n        .ok()\n        .map(|r| *r)\n}","tryCatchPattern":null,"preventionTips":["Rebuild artifacts with the union toolchain whenever the note fails to parse","Check section presence and size with readelf before verifying","Never hand-craft .note.embed_commit.GIT_REV sections","Pin matching embed-commit crate versions across build and verify environments"],"tags":["elf","build-metadata","verification","embed-commit","bytemuck","rust"],"backgroundTag":null,"analyzedSha":"031785bb6dc6b957c624e62bc64c184409c97d7b","analyzedAt":"2026-08-16T06:24:09.996Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}