{"record":{"id":"c4f7d2671be31a1d","repo":"GitoxideLabs/gitoxide","slug":"base-graph-count-to-fit-in-32-bits","errorCode":null,"errorMessage":"base graph count to fit in 32-bits","messagePattern":"base graph count to fit in 32-bits","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-commitgraph/src/file/init.rs","lineNumber":78,"sourceCode":"\n        let chunks = gix_chunk::file::Index::from_bytes(&data, ofs, u32::from(chunk_count))\n            .or_raise(|| message!(\"Couldn't read commit-graph file with {chunk_count} chunks at offset {ofs}\"))?;\n\n        let base_graphs_list_offset = chunks\n            .validated_usize_offset_by_id(BASE_GRAPHS_LIST_CHUNK_ID, |chunk_range| {\n                let chunk_size = chunk_range.len();\n                if chunk_size % object_hash.len_in_bytes() != 0 {\n                    return Err(message!(\"Commit-graph chunk {BASE_GRAPHS_LIST_CHUNK_ID:?} has invalid size: {msg}\",\n                        msg = format!(\n                            \"chunk size {} is not a multiple of {}\",\n                            chunk_size,\n                            object_hash.len_in_bytes()\n                        ),\n                    ).raise());\n                }\n                let chunk_base_graph_count: u32 = (chunk_size / object_hash.len_in_bytes())\n                    .try_into()\n                    .expect(\"base graph count to fit in 32-bits\");\n                if chunk_base_graph_count != u32::from(base_graph_count) {\n                    return Err(message!(\"Commit-graph {BASE_GRAPHS_LIST_CHUNK_ID:?} chunk contains {chunk_base_graph_count} base graphs, but commit-graph file header claims {base_graph_count} base graphs\").raise())\n                }\n                Ok(chunk_range.start)\n            })\n            .ok()\n            .transpose()?;\n\n        let (commit_data_offset, commit_data_count): (_, u32) = chunks\n            .validated_usize_offset_by_id(COMMIT_DATA_CHUNK_ID, |chunk_range| {\n                let chunk_size = chunk_range.len();\n\n                let entry_size = object_hash.len_in_bytes() + COMMIT_DATA_ENTRY_SIZE_SANS_HASH;\n                if chunk_size % entry_size != 0 {\n                    return Err(message!(\"Commit-graph chunk {COMMIT_DATA_CHUNK_ID:?} has invalid size: chunk size {chunk_size} is not a multiple of {entry_size}\").raise())\n                }\n                Ok((\n                    chunk_range.start,","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-commitgraph/src/file/init.rs#L60-L96","documentation":"When initializing a commit-graph File, the BASE_GRAPHS_LIST chunk size divided by the hash length must fit into a u32, since the count of base graphs is a 32-bit quantity in the format. The `try_into()` is expected to succeed because the chunk is already validated. This panic means the chunk file is structurally corrupt or the header/base-graph count disagrees in an unexpected way.","triggerScenarios":"Calling `gix_commitgraph::File::at()` (public `new`) on a commit-graph file whose BASE_GRAPHS_LIST chunk is larger than u32::MAX hash entries — i.e. a corrupt or adversarially crafted commit-graph file.","commonSituations":"Reading a corrupted or hand-crafted commit-graph file; a repository with a malformed .git/objects/info/commit-graph; fuzzing targets; a git version producing non-standard graphs.","solutions":["Delete and regenerate the commit-graph: `rm .git/objects/info/commit-graph* && git commit-graph write`","Validate the commit-graph file before use; treat unreadable graphs as optional and fall back to object parsing","Report upstream if reproducible with a valid git-generated commit-graph"],"exampleFix":"// before\nlet f = gix_commitgraph::File::at(path, hash)?;\n// after (guard at call site)\nlet f = if path.exists() { gix_commitgraph::File::at(path, hash).ok() } else { None };","handlingStrategy":"fallback","validationCode":"// verify chunk sizes before trusting the file\nif file_len < expected_min_len { skip_commitgraph(); }","typeGuard":null,"tryCatchPattern":"let graph = gix_commitgraph::File::at(path, hash).map_err(|e| e.into_error()).ok();","preventionTips":["Never treat commit-graph load failure as fatal — it is a performance cache","Regenerate commit-graphs after git version upgrades","Sanity-check commit-graph file size before opening"],"tags":["rust","panic","commitgraph","corrupt-file","overflow"],"backgroundTag":"internal-invariant-violation","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}