Some checks failed
standards workspaces build + test / jouleclaw-rs (pull_request) Successful in 2m13s
standards workspaces build + test / aac-rs (pull_request) Successful in 1m58s
standards workspaces build + test / joule-code-rs (pull_request) Successful in 50s
standards workspaces build + test / joulecontract-rs (pull_request) Successful in 34s
standards workspaces build + test / map-rs (pull_request) Successful in 31s
standards workspaces build + test / mesh-rs (pull_request) Successful in 31s
no-vanity-metrics / Scan committed Markdown for vanity metrics (pull_request) Has been cancelled
no-vanity-metrics / WAI public text names no comparison (pull_request) Has been cancelled
no-vanity-metrics / WAI public text names no company or product (pull_request) Has been cancelled
standards workspaces build + test / arl-rs (pull_request) Has been cancelled
standards workspaces build + test / eoc-rs (pull_request) Has been cancelled
standards workspaces build + test / jcp-rs (pull_request) Has been cancelled
standards workspaces build + test / joule-ui-rs (pull_request) Has been cancelled
standards workspaces build + test / jouledesk-rs (pull_request) Has been cancelled
standards workspaces build + test / joulehook-rs (pull_request) Has been cancelled
standards workspaces build + test / proof-rs (pull_request) Has been cancelled
standards workspaces build + test / sandbox-rs (pull_request) Has been cancelled
standards workspaces build + test / sense-rs (pull_request) Has been cancelled
standards workspaces build + test / smart-byte-rs (pull_request) Has been cancelled
standards workspaces build + test / macOS energy backends (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cargo-class corpora · macos (pull_request) Has been cancelled
WAI conformance / quantum core and corpus under wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
WAI conformance / v2 vocabulary · manifests validate as stated (pull_request) Has been cancelled
WAI conformance / independent verifiers · claims, JWP, key discovery and integer payloads (Python) (pull_request) Has been cancelled
WAI conformance / delivery telemetry · CMCD and CMSD against an independent library (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · linux-arm64 (pull_request) Has been cancelled
WAI conformance / cross-arch byte-equality · macos (pull_request) Has been cancelled
WAI conformance / C2PA manifest emission · signed, read back, validated (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux (pull_request) Has been cancelled
WAI energy receipts / energy receipts · linux-arm64 (pull_request) Has been cancelled
WAI energy receipts / energy receipts · macos (pull_request) Has been cancelled
WAI section references / cited sections exist (pull_request) Has been cancelled
wai-vector vector graphics / linux-aarch64 (pull_request) Has been cancelled
wai-vector vector graphics / linux-x86_64 (pull_request) Has been cancelled
wai-vector vector graphics / macos-arm64 (pull_request) Has been cancelled
wai-vector vector graphics / wasm32-wasip2 (wasmtime) (pull_request) Has been cancelled
wai-vector vector graphics / wasm32 under Node (pull_request) Has been cancelled
wai-vector vector graphics / fuzz, peak allocation, comparison count (pull_request) Has been cancelled
workflow hygiene / every workflow supersedes its own queue (pull_request) Has been cancelled
standards workspaces build + test / openpay (pull_request) Has been cancelled
The reference crate of wai.graphics.vector (no_std + alloc, no dependencies; SHA-256 is wai-ops's, by #[path]): - WOS1 parsed with §2.1's load checks in order, and written; - WVG1 split (steps 1-3, nothing allocated before the exact length), the record pass (step 4), the cross-record checks (step 5(a)-(h)), the sets by digest with at most length + 1 bytes read (step 6), the glyphs (7), the interval check (8) and the per-frame cost (9); - the clock with the frame range by division, track evaluation, and placement; - the JSON authoring form, one member per field, packing back to the same bytes; - the CLI: check, cost, pack, unpack, vectors gen and verify; - a wasm32 module and verify.mjs for Node. The corpus wai/vector-conformance/ (arith, canonical, refusals, geometry, cost) with its README's provenance line and a sha256.json sidecar naming the div255 table; wai-vector.yml with native, wasip2, node and fuzz jobs. Co-Authored-By: Claude Opus 5.5 <[email protected]>
135 lines
6.6 KiB
Rust
135 lines
6.6 KiB
Rust
//! §3.4: the load-time interval check and the per-frame cost, at their boundaries, and
|
||
//! review A's attack payloads refused with the codes §2.7 gives.
|
||
|
||
use wai_vector::bounds::{COST_CEILING, DEVICE_MAX, DEVICE_MIN};
|
||
use wai_vector::place::{self, fill_cost, origin, point_offset, linear_map};
|
||
use wai_vector::refuse::Code;
|
||
use wai_vector::track::eval;
|
||
use wai_vector::vectors::{corpus_store, find};
|
||
use wai_vector::wvg1::{self, NoSets};
|
||
|
||
fn load(group: &str, name: &str) -> Result<wvg1::Loaded, wai_vector::Refusal> {
|
||
let v = find(group, name).unwrap_or_else(|| panic!("no vector {group}/{name}"));
|
||
wvg1::load(&v.bytes, &mut corpus_store())
|
||
}
|
||
|
||
#[test]
|
||
fn interval_check_boundary() {
|
||
for name in ["x-high-edge", "x-low-edge", "y-high-edge", "empty-glyph-edge"] {
|
||
assert!(load("geometry", name).is_ok(), "{name}: an end at the range's edge is accepted");
|
||
}
|
||
for name in ["x-high-over", "x-low-over", "y-high-over", "second-size-over", "inactive-item-over", "clip-over", "groups-sum-over", "empty-glyph-over"] {
|
||
assert_eq!(load("geometry", name).unwrap_err().code, Code::GeometryRange, "{name}");
|
||
}
|
||
}
|
||
|
||
/// The rule is the interval computation, not the true range: this document's device
|
||
/// x reaches exactly 2^22 − 1 at every tick, and it is refused.
|
||
#[test]
|
||
fn interval_not_true_range() {
|
||
let v = find("geometry", "true-range-fits").unwrap();
|
||
let d = wvg1::parse(&v.bytes).unwrap();
|
||
// The true range, evaluated at every tick of the item's window and every corner.
|
||
let it = &d.items[0];
|
||
let (w, dw) = (i64::from(d.sizes[0].w), i64::from(d.header.design_w));
|
||
let track = |s: usize| d.track_keys(it.slots[s] as usize);
|
||
let bx = d.paths[0].bbox;
|
||
let (mut lo, mut hi) = (i64::MAX, i64::MIN);
|
||
for tau in i64::from(it.t_on)..i64::from(it.t_off) {
|
||
let m = [eval(track(0), &d.tables, tau), eval(track(1), &d.tables, tau), 0, 65_536];
|
||
let l = linear_map(m, i64::from(it.unit_scale), w, dw);
|
||
let t = origin([eval(track(4), &d.tables, tau), 0], m, [0, 0], w, dw);
|
||
for px in [bx[0], bx[2]] {
|
||
for py in [bx[1], bx[3]] {
|
||
let x = t[0] + point_offset(l, [i64::from(px), i64::from(py)])[0];
|
||
lo = lo.min(x);
|
||
hi = hi.max(x);
|
||
}
|
||
}
|
||
}
|
||
assert!(DEVICE_MIN <= lo && hi == DEVICE_MAX, "the true range [{lo}, {hi}] fits, its end at 2^22 - 1");
|
||
assert_eq!(load("geometry", "true-range-fits").unwrap_err().code, Code::GeometryRange);
|
||
}
|
||
|
||
#[test]
|
||
fn cost_ceiling_boundary() {
|
||
let l = load("cost", "ceiling").expect("a cost of exactly 2^32 - 1 is accepted");
|
||
assert_eq!(l.costs, vec![COST_CEILING]);
|
||
assert_eq!(load("cost", "ceiling-plus-one").unwrap_err().code, Code::TooLarge);
|
||
let e = load("cost", "ceiling-stated-low").unwrap_err();
|
||
assert_eq!((e.code, e.step), (Code::PayloadMalformed, "9"), "a stated cost off by one");
|
||
let e = load("cost", "reused-path-stated-high").unwrap_err();
|
||
assert_eq!((e.code, e.step), (Code::PayloadMalformed, "9"));
|
||
}
|
||
|
||
/// Each use of a reused path counts: three fills of one 4-point path whose box is
|
||
/// 11 × 11 pixels at 640 × 360.
|
||
#[test]
|
||
fn cost_counts_a_reused_path_per_use() {
|
||
let one = 4 * (1024 + 11 + 11) + 11 * 11;
|
||
assert_eq!(fill_cost(4, 11, 11), one);
|
||
assert_eq!(load("cost", "reused-path").unwrap().costs, vec![640 * 360 + 3 * one]);
|
||
assert_eq!(load("cost", "touching-windows").unwrap().costs, vec![640 * 360 + one], "touching windows count once");
|
||
// A group: w·h, plus its clip (101 × 51 pixels, 4 points), plus its child.
|
||
let clip = fill_cost(4, 101, 51);
|
||
assert_eq!(load("cost", "group").unwrap().costs, vec![2 * 640 * 360 + clip + one]);
|
||
}
|
||
|
||
#[test]
|
||
fn review_a_attack_payloads_are_refused() {
|
||
for name in ["attack-a-reused-full-canvas", "attack-b-reused-cubic-path", "attack-c-full-canvas-glyphs"] {
|
||
let e = load("cost", name).unwrap_err();
|
||
assert_eq!((e.code, e.step), (Code::TooLarge, "9"), "{name}: the cost exceeds the ceiling");
|
||
}
|
||
let one = load("cost", "attack-b-one-item").expect("one heavy item alone is accepted");
|
||
assert_eq!(one.costs, vec![4096 * 4096 + fill_cost(16_381, 4096, 4096)]);
|
||
for name in ["attack-d-64-held-sets", "attack-d-3-held-sets"] {
|
||
let e = load("refusals", name).unwrap_err();
|
||
assert_eq!((e.code, e.step), (Code::TooLarge, "2"), "{name}: held_len past 2^26 before anything is fetched");
|
||
}
|
||
assert_eq!(load("refusals", "attack-d-2-held-sets").unwrap_err().code, Code::OutlineNotHeld);
|
||
let e = load("refusals", "attack-e-duplicate-tracks").unwrap_err();
|
||
assert_eq!((e.code, e.step), (Code::PayloadMalformed, "5g"));
|
||
// The cost needs nothing but the payload and its sets: computed again here.
|
||
let v = find("cost", "attack-a-reused-full-canvas").unwrap();
|
||
let d = wvg1::parse(&v.bytes).unwrap();
|
||
let sets = wvg1::load_sets(&d, &mut NoSets).unwrap();
|
||
assert_eq!(place::costs(&d, &sets), vec![4096 * 4096 + 260 * fill_cost(4, 4096, 4096)]);
|
||
}
|
||
|
||
/// Review A's three shapes at full scale, built in memory: the cost reproduces the
|
||
/// figures RC2 recomputed for the design (A: 65,536 fills of a full-canvas
|
||
/// rectangle; C: 2^20 full-canvas glyph records in 256 runs of 4,096, with each run's
|
||
/// hull term), and B's from its formula.
|
||
#[test]
|
||
fn review_a_full_scale_costs() {
|
||
let cost_of = |d: &wvg1::Doc| {
|
||
let d = wvg1::parse(&d.write()).expect("steps 1-5");
|
||
let sets = wvg1::load_sets(&d, &mut NoSets).expect("inline sets");
|
||
place::costs(&d, &sets)
|
||
};
|
||
let mut a = wvg1::parse(&find("cost", "attack-a-reused-full-canvas").unwrap().bytes).unwrap();
|
||
let item = a.items[0];
|
||
a.items = vec![item; 65_536];
|
||
a.sync_counts();
|
||
assert_eq!(cost_of(&a), vec![1_101_944_324_096]);
|
||
let mut b = wvg1::parse(&find("cost", "attack-b-reused-cubic-path").unwrap().bytes).unwrap();
|
||
let item = b.items[0];
|
||
b.items = vec![item; 65_536];
|
||
b.sync_counts();
|
||
// RC2 counted 5,460 cubics as 16,380 points (10,992,717,135,872); the path stores
|
||
// the start point too, 16,381.
|
||
assert_eq!(cost_of(&b), vec![4096 * 4096 + 65_536 * fill_cost(16_381, 4096, 4096)]);
|
||
assert_eq!(4096 * 4096 + 65_536 * fill_cost(16_380, 4096, 4096), 10_992_717_135_872);
|
||
let mut c = wvg1::parse(&find("cost", "attack-c-full-canvas-glyphs").unwrap().bytes).unwrap();
|
||
let mut run = c.items[0];
|
||
run.n_glyphs = 4096;
|
||
let g = c.glyphs[0];
|
||
let mut cl = c.clusters[0];
|
||
cl.glyph_count = 4096;
|
||
c.items = vec![run; 256];
|
||
c.glyphs = vec![g; 1 << 20];
|
||
c.clusters = vec![cl; 256];
|
||
c.sync_counts();
|
||
assert_eq!(cost_of(&c), vec![17_635_152_494_592]);
|
||
}
|