Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

update-bundle/tests/openzl_alloc_budget.rs

//! **A 36-byte OpenZL frame cannot make the bundle verifier allocate a gigabyte.**
//!
//! The heimdall fuzz find (lane zlwasm, `fixtures/fuzz/regress-constant-stream-alloc.zl`):
//! a frame whose header declares 0 bytes and whose `constant` codec asks OpenZL for a
//! stream of ~2^64 bytes. With the element count set to 2^30, the same 36 bytes made
//! OpenZL allocate and fill 1 GiB natively before failing (lane gatwasm, 2026-10-31).
//! Here it is `core.json`, a control member, which is extracted BEFORE the release
//! signature is checked. znippy-common 0.10.4 decodes every chunk of a verified read
//! under an OpenZL allocation budget (openzl-sys-rs 0.4.2), so the bundle is refused
//! as a malformed container and the process does not grow.
//!
//! Its own test binary, so the process peak (VmHWM) it reads is its own.

use std::fs::File;
use std::os::unix::fs::FileExt;
use std::path::Path;
use std::sync::Arc;

use holger_update_bundle::container::load_bundle_verified;
use holger_update_bundle::policy::TrustPolicy;
use znippy_common::index::{build_metadata_batch, lookup_schema};
use znippy_common::meta::{BlobMeta, ChunkMeta};
use znippy_common::meta_sink::{ArchiveMetaSink, ArrowIpcSink, GroupKey};

fn peak_rss_mib() -> u64 {
    let s = std::fs::read_to_string("/proc/self/status").unwrap_or_default();
    s.lines()
        .find(|l| l.starts_with("VmHWM:"))
        .and_then(|l| l.split_whitespace().nth(1))
        .and_then(|v| v.parse::<u64>().ok())
        .map(|kib| kib / 1024)
        .unwrap_or(0)
}

/// The fuzz frame with its 10-byte element-count varint (offset 0x11) set to `n`.
fn constant_frame_with_count(n: u64) -> Vec<u8> {
    let p = Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests/fixtures/fuzz/regress-constant-stream-alloc.zl");
    let mut frame = std::fs::read(p).unwrap();
    let mut v = n;
    for i in 0..10 {
        frame[0x11 + i] = (v & 0x7f) as u8 | if i < 9 { 0x80 } else { 0 };
        v >>= 7;
    }
    frame
}

/// A bundle whose only member, `core.json`, is one compressed chunk holding
/// `frame`, declared `declared` bytes by the index.
fn write_bundle(path: &Path, frame: &[u8], declared: u64) {
    let file = Arc::new(File::create(path).unwrap());
    file.write_all_at(frame, 0).unwrap();
    let blobs = vec![BlobMeta {
        blob_offset: 0,
        blob_size: frame.len() as u64,
        chunk_meta: ChunkMeta {
            fdata_offset: 0,
            file_index: 0,
            chunk_seq: 0,
            checksum: [0u8; 32],
            compressed: true,
            uncompressed_size: declared,
            compressed_size: frame.len() as u64,
        },
    }];
    let batch = build_metadata_batch(&blobs, |_| "core.json".to_string(), &[], &[]).unwrap();
    let mut sink = ArrowIpcSink::new(file.clone(), frame.len() as u64);
    sink.push_subindex(
        lookup_schema().as_ref(),
        &[batch],
        GroupKey {
            pkg_type: 0,
            repo: String::new(),
            module_name: String::new(),
        },
    )
    .unwrap();
    Box::new(sink).finish().unwrap();
}

#[test]
fn a_gigabyte_constant_stream_in_core_json_is_refused_without_growing_memory() {
    let dir = std::env::temp_dir().join(format!("holger-zlbudget-{}", std::process::id()));
    std::fs::create_dir_all(&dir).unwrap();
    let path = dir.join("hostile.holger.znippy");
    write_bundle(&path, &constant_frame_with_count(1 << 30), 16);
    let policy = TrustPolicy::from_ron(
        r#"(schema_version: "holger.bundle-trust-policy/v1", trust_mode: Some(PinnedSigners))"#,
    )
    .unwrap();

    let before = peak_rss_mib();
    let got = load_bundle_verified(&path, &policy);
    let grew = peak_rss_mib().saturating_sub(before);
    let _ = std::fs::remove_dir_all(&dir);

    let e = got.expect_err("the hostile bundle is refused");
    let msg = e.to_string();
    assert!(
        msg.contains("cannot extract bundle member"),
        "a container refusal: {msg}"
    );
    assert!(
        msg.contains("allocation budget"),
        "refused by the OpenZL allocation budget: {msg}"
    );
    assert!(
        grew < 64,
        "a 36-byte frame grew the verifier's peak by {grew} MiB"
    );
}