source2rosetta/fuzz/fuzz_targets/fuzz_schema.rs
Kamal Tufekcic 3410a79b6a
Some checks failed
CI / fuzz (push) Successful in 2m2s
CI / lint (push) Successful in 15s
CI / test (push) Failing after 18s
ship one record per function: merge the release set, gen reads it, descriptions as doc comments, gates for what was only claimed; v3.0
2026-08-02 22:01:36 +03:00

36 lines
1.5 KiB
Rust

#![no_main]
//! The Source-2 SchemaSystem reader walks reloc-slot candidates as `SchemaClassInfoData_t` structs,
//! chasing `m_pFields`/`m_pBaseClasses` pointers. A crafted (or truncated) `.so` can point those
//! anywhere; the reader must survive it with `Err`/empty, never a panic. Also exercises the field and
//! base-class accessors the derivation reads.
use source2rosetta::elf::CodeImage;
use source2rosetta::schema;
use libfuzzer_sys::fuzz_target;
fuzz_target!(|data: &[u8]| {
let Ok(img) = CodeImage::from_bytes(data.to_vec()) else {
return;
};
// The enum bindings are a SECOND table read the same reloc-driven way: a name pointer, a
// width/count word, and an enumerator array whose length that word supplies. A crafted count is the
// sharp edge — it drives the per-enumerator read loop — so the reader must bound it rather than
// trust it.
let classes = schema::enumerate_schema(&img);
// The enum walk takes the classes because a class FIELD descriptor is byte-compatible with an enum
// binding — so a crafted image can aim the field-array spans it derives from them anywhere too.
for e in schema::enumerate_enums(&img, &classes) {
let _ = (e.name.len(), e.size, e.align);
for (n, v) in &e.values {
let _ = (n.len(), *v);
}
}
for c in &classes {
let _ = c.primary_base();
for f in &c.fields {
let _ = (f.offset, f.name.len());
}
for b in &c.bases {
let _ = (b.offset, b.name.len());
}
}
});