Gunnar

nordisk/heimdall

crates/heimdall-run/tests/fuzz_seeds.rs

// SPDX-License-Identifier: AGPL-3.0-only
//! The fuzz targets' invariants, replayed over the checked-in seed corpus and
//! a burst of random inputs on every ordinary test run (no nightly needed).
//! Heimdall is a defensive sandbox; these are its own parsers.

use std::path::PathBuf;

use heimdall_run::fuzz_api;
use proptest::prelude::*;

fn seeds(target: &str) -> Vec<Vec<u8>> {
    let dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("../../fuzz/seeds")
        .join(target);
    let mut v: Vec<_> = std::fs::read_dir(&dir)
        .unwrap_or_else(|e| panic!("{}: {e}", dir.display()))
        .map(|e| std::fs::read(e.unwrap().path()).unwrap())
        .collect();
    v.sort();
    v
}

#[test]
fn policy_file_fuzz_invariants_hold_on_every_seed() {
    let s = seeds("policy_file");
    assert!(s.len() >= 5);
    for b in s {
        fuzz_api::policy_file(&b);
    }
}

#[test]
fn output_name_fuzz_invariants_hold_on_every_seed() {
    let s = seeds("output_name");
    assert!(s.len() >= 5);
    for b in s {
        fuzz_api::output_name(&b);
    }
}

proptest! {
    #![proptest_config(ProptestConfig::with_cases(2000))]

    #[test]
    fn prop_policy_file_fuzz_invariants_hold_on_toml_shaped_input(
        body in "(version = [0-9]{1,3}\n)?(\\[(limits|job|net)\\]\n)?([a-z_]{1,22} = (-?[0-9]{1,21}|\"[a-z]{0,6}\"|[0-9]\\.[0-9])\n){0,6}"
    ) {
        fuzz_api::policy_file(body.as_bytes());
    }

    #[test]
    fn prop_output_name_fuzz_invariants_hold_on_random_bytes(b in proptest::collection::vec(any::<u8>(), 0..160)) {
        fuzz_api::output_name(&b);
    }
}

#[test]
fn verify_result_file_fuzz_invariants_hold_on_every_seed() {
    let s = seeds("verify_result_file");
    assert!(s.len() >= 5);
    for b in s {
        fuzz_api::verify_result_file(&b);
    }
}

#[test]
fn verify_result_file_fuzz_entry_verifies_its_own_fixture_key_and_refuses_flips() {
    use heimdall_core::{BootId, BootKey, JobId, JobResult, Nonce, Verdict};
    let key = BootKey::from_seed([9; 32], BootId([1; 16]));
    let r = JobResult {
        job_id: JobId([2; 16]),
        nonce: Nonce([3; 32]),
        verdict: Verdict::Accepted,
        outputs: vec![],
        exit: heimdall_core::ExitInfo::exited(0),
        started_unix: 1,
        finished_unix: 2,
        runner: heimdall_run::job::wasm_features(),
        events: vec![],
    };
    let wire = key.sign(r).unwrap().to_bytes();
    let pinned = key.pinned();
    assert!(heimdall_run::verify::verify_result(&wire, pinned, None, None).is_ok());
    fuzz_api::verify_result_file(&wire);
    let mut flipped = wire.clone();
    flipped[20] ^= 0x80;
    assert!(heimdall_run::verify::verify_result(&flipped, pinned, None, None).is_err());
}