Gunnar

nordisk/heimdall

crates/heimdall-run/src/fuzz_api.rs

// SPDX-License-Identifier: AGPL-3.0-only
//! Entry points the cargo-fuzz targets (`fuzz/`) drive. Each one panics only
//! when an invariant breaks, so the fuzzer reports exactly that. The same
//! functions run over a seed corpus in the ordinary test suite.
//!
//! Heimdall is a defensive sandbox; these are its own parsers.

use std::path::{Component, Path};

use crate::policy_file::PolicyFile;

/// Parse arbitrary bytes as a policy file. An accepted file must have every
/// limit between 1 and its ceiling and the file cap within the total cap.
pub fn policy_file(data: &[u8]) {
    if let Ok(p) = PolicyFile::from_bytes(data) {
        let c = crate::RunLimits::ceilings();
        let l = p.limits;
        assert!(l.fuel >= 1 && l.fuel <= c.fuel);
        assert!(l.wall_time_ms >= 1 && l.wall_time_ms <= c.wall_time_ms);
        assert!(l.memory_bytes >= 1 && l.memory_bytes <= c.memory_bytes);
        assert!(l.table_elements >= 1 && l.table_elements <= c.table_elements);
        assert!(l.instances >= 1 && l.instances <= c.instances);
        assert!(l.tables >= 1 && l.tables <= c.tables);
        assert!(l.memories >= 1 && l.memories <= c.memories);
        assert!(l.stack_bytes >= 1 && l.stack_bytes <= c.stack_bytes);
        assert!(l.max_input_bytes >= 1 && l.max_input_bytes <= c.max_input_bytes);
        assert!(l.max_output_files >= 1 && l.max_output_files <= c.max_output_files);
        assert!(l.max_output_file_bytes >= 1 && l.max_output_file_bytes <= c.max_output_file_bytes);
        assert!(l.max_output_file_bytes <= l.max_output_total_bytes);
        assert!(l.max_output_total_bytes <= c.max_output_total_bytes);
        assert!(p.job.is_none() || p.job.as_deref() == Some("wasm"));
    }
}

/// Check arbitrary bytes as an output name. An accepted name is one plain,
/// non-hidden path component.
pub fn output_name(data: &[u8]) {
    if let Ok(name) = crate::outdir::validate_output_name_bytes(data) {
        let comps: Vec<_> = Path::new(name).components().collect();
        assert_eq!(comps.len(), 1);
        assert!(matches!(comps[0], Component::Normal(_)));
        assert!(!name.starts_with('.'));
        assert!(heimdall_core::validate_output_name(name).is_ok());
    }
}

/// Verify arbitrary bytes as a result file under a fixed pinned key, the way
/// `heimdall verify-result` does. Bytes that verify must be canonical: they
/// re-encode to exactly the input.
pub fn verify_result_file(data: &[u8]) {
    use heimdall_core::{BootId, BootKey};
    let key = BootKey::from_seed([9; 32], BootId([1; 16]));
    if let Ok(v) = crate::verify::verify_result(data, key.pinned(), None, None) {
        assert_eq!(v.signed.to_bytes(), data);
        assert_eq!(v.files_checked, 0);
    }
}