#![no_main] use clawhdf5_format::btree_v2::{BTreeV2Header, collect_btree_v2_records}; use libfuzzer_sys::fuzz_target; fuzz_target!(|data: &[u8]| { for &offset_size in &[4u8, 8] { for &length_size in &[4u8, 8] { if let Ok(header) = BTreeV2Header::parse(data, 0, offset_size, length_size) { let _ = collect_btree_v2_records(data, &header, offset_size, length_size); } } } // Parsing a header requires a valid checksum, which random input almost // never has, so the traversal behind it went unfuzzed — and that is where // a node listing itself as its own child overflowed the stack. Take the // header fields straight from the input instead and walk the rest. let Some((fields, file)) = data.split_first_chunk::<20>() else { return; }; let header = BTreeV2Header { tree_type: fields[0], node_size: u32::from_le_bytes([fields[1], fields[2], fields[3], fields[4]]), record_size: u16::from_le_bytes([fields[5], fields[6]]), depth: u16::from_le_bytes([fields[7], fields[8]]), root_node_address: u64::from(u32::from_le_bytes([ fields[9], fields[10], fields[11], fields[12], ])), num_records_in_root: u16::from_le_bytes([fields[13], fields[14]]), total_records: u64::from(u32::from_le_bytes([ fields[15], fields[16], fields[17], fields[18], ])), }; let offset_size = if fields[19] & 1 == 0 { 4 } else { 8 }; let _ = collect_btree_v2_records(file, &header, offset_size, 8); });