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

mikronova/openzl-sys-rs

tests/alloc_budget.rs

//! The allocation budget (`with_alloc_budget`): a hostile frame cannot make
//! OpenZL allocate past it, an honest frame decodes under it, and a thread
//! without one is unchanged.

use openzl_sys_rs::*;

/// The heimdall fuzz frame with its element count (10-byte varint at 0x11) set to `n`.
fn constant_frame_with_count(n: u64) -> Vec<u8> {
    let mut frame = include_bytes!("fixtures/regress-constant-stream-alloc.zl").to_vec();
    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
}

fn honest_frame(len: usize) -> (Vec<u8>, Vec<u8>) {
    let src: Vec<u8> = (0..len as u32).map(|x| ((x * 31 + x / 7) % 253) as u8).collect();
    let mut c = ZlCCtx::new().unwrap();
    c.set_parameter(ZL_CParam_ZL_CParam_formatVersion, 25).unwrap();
    c.set_parameter(ZL_CParam_ZL_CParam_compressionLevel, 3).unwrap();
    let mut frame = vec![0u8; zl_compress_bound(src.len())];
    let n = c.compress(&mut frame, &src).unwrap();
    frame.truncate(n);
    (src, frame)
}

#[test]
fn a_hostile_frame_is_refused_at_the_budget() {
    // 2^24 elements: big enough to be refused by a 1 MiB budget, small enough
    // that the test is harmless if the budget is not enforced.
    let frame = constant_frame_with_count(1 << 24);
    let mut out = [0u8; 16];
    let (got, spent) = with_alloc_budget(1 << 20, || zl_decompress(&mut out, &frame));
    assert!(got.is_err(), "the frame is refused");
    assert!(spent.exceeded, "the refusal was the budget's: {spent:?}");
    assert!(spent.used <= spent.limit, "nothing was charged past the limit: {spent:?}");
}

#[test]
fn an_honest_frame_decodes_under_a_budget_and_is_charged() {
    let (src, frame) = honest_frame(1 << 20);
    let mut out = vec![0u8; src.len()];
    let (got, spent) = with_alloc_budget(64 << 20, || zl_decompress(&mut out, &frame));
    assert_eq!(got.unwrap(), src.len());
    assert_eq!(out, src);
    assert!(!spent.exceeded, "{spent:?}");
    assert!(spent.used > 0, "OpenZL's allocations are charged: {spent:?}");
}

#[test]
fn a_thread_without_a_budget_is_unchanged() {
    let (src, frame) = honest_frame(1 << 20);
    let mut out = vec![0u8; src.len()];
    // Spend a budget first: it must not linger on the thread.
    let _ = with_alloc_budget(1, || ());
    assert_eq!(zl_decompress(&mut out, &frame).unwrap(), src.len());
    assert_eq!(out, src);
}

#[test]
fn budgets_nest_and_restore() {
    let (src, frame) = honest_frame(1 << 20);
    let hostile = constant_frame_with_count(1 << 24);
    let mut out = vec![0u8; src.len()];
    let ((inner, ok), outer) = with_alloc_budget(64 << 20, || {
        let mut small = [0u8; 16];
        let (inner, _) = with_alloc_budget(1 << 20, || zl_decompress(&mut small, &hostile));
        (inner, zl_decompress(&mut out, &frame))
    });
    assert!(inner.is_err());
    assert_eq!(ok.unwrap(), src.len());
    assert!(!outer.exceeded, "the inner refusal is not the outer budget's: {outer:?}");
    assert!(outer.used > 0, "the outer budget is back in force after the inner one: {outer:?}");
}

#[test]
fn the_budget_is_restored_on_unwind() {
    let hostile = constant_frame_with_count(1 << 24);
    let r = std::panic::catch_unwind(|| with_alloc_budget(1 << 20, || panic!("boom")));
    assert!(r.is_err());
    // No budget is left behind: the frame fails on its own terms, not the budget's.
    let mut out = [0u8; 16];
    let (_, spent) = with_alloc_budget(usize::MAX, || zl_decompress(&mut out, &hostile));
    assert!(!spent.exceeded);
}