// 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());
}