test(tools): h5rs sweeps over the conformance corpora

scripts/h5rs-fuzz.sh runs every h5rs subcommand over every file of a corpus
(default: the HDF Group's CVE reproducers), optionally with byte-flipped
copies (MUTATE=N), under a timeout and a memory limit, with a debug build so
integer overflow panics instead of wrapping; any exit status above 2 (a
caught panic, a timeout, a signal) fails it. It found size*8 overflows in
the datatype names on cve-2021-46244.h5, cve-2024-29161.h5 and unknown-1.h5
(fixed in the crate before it landed).

scripts/h5rs-check-ok-files.sh runs check (--data) over the conformance
files that clawhdf5 and h5py both read in full; none may be flagged.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
osobh
2026-09-26 00:29:34 -05:00
co-authored by Claude Opus 5.5
parent 310448bfcb
commit 40968b3578
2 changed files with 194 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
#!/usr/bin/env bash
# scripts/h5rs-check-ok-files.sh — run `h5rs check` over the files the
# conformance sweep reads correctly and completely: the `ok_files` of
# conformance/baseline.json (clawhdf5 and h5py agree on every object) whose
# probe results record no error at all (some ok files are deliberately
# corrupt test files that both readers refuse in the same way; those are
# left out). A validator that flags a file libhdf5 and clawhdf5 both read
# in full has a false positive — unless the file really is damaged in a way
# readers tolerate, which the report must then show.
#
# Usage: scripts/h5rs-check-ok-files.sh [--data] [SAMPLE]
# --data pass --data to check (decode every chunk)
# SAMPLE check only every SAMPLE-th file (default 1: all of them)
#
# Environment: H5RS (binary; default builds release), CONFORMANCE_CACHE
# (corpus cache, default conformance/.cache), CONFORMANCE_OUT (the sweep's
# results, default $CONFORMANCE_CACHE/results; run conformance/run.sh first),
# TMO (timeout, default 60).
#
# Exit status: 0 = no file flagged; 1 = some file flagged or failed (listed);
# 2 = setup error.
set -uo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(cd "$HERE/.." && pwd)"
export PATH="$HOME/.cargo/bin:$PATH"
DATA=()
if [ "${1:-}" = "--data" ]; then DATA=(--data); shift; fi
SAMPLE="${1:-1}"
CACHE="${CONFORMANCE_CACHE:-$ROOT/conformance/.cache}"
C="$CACHE/corpus"
R="${CONFORMANCE_OUT:-$CACHE/results}"
[ -d "$C" ] || { echo "error: no corpus in $C (run conformance/fetch-corpus.sh)" >&2; exit 2; }
[ -d "$R/runs" ] || { echo "error: no sweep results in $R (run conformance/run.sh)" >&2; exit 2; }
if [ -z "${H5RS:-}" ]; then
cargo build -q --release -p clawhdf5-tools --manifest-path "$ROOT/Cargo.toml" || exit 2
H5RS="${CARGO_TARGET_DIR:-$ROOT/target}/release/h5rs"
fi
TMO="${TMO:-60}"
mapfile -t FILES < <(python3 -c '
import json, os, sys
b = json.load(open(sys.argv[1]))
runs, step = sys.argv[3], int(sys.argv[2])
def clean(f):
"""Both readers read every object, attribute and group listing."""
for side in ("ours.json", "ref.json"):
try:
d = json.load(open(os.path.join(runs, f.replace("/", "__"), side)))
except (OSError, ValueError):
return False
if "open_error" in d or d.get("truncated"):
return False
for o in d.get("objects", []):
if "error" in o or "attrs_error" in o or "list_error" in o:
return False
if any(isinstance(a, dict) and "error" in a for a in o.get("attrs", {}).values()):
return False
return True
files = [f for f in b["ok_files"] if clean(f)]
total = len(b["ok_files"])
print(f"{len(files)} of {total} ok files are read in full by both readers", file=sys.stderr)
for i, f in enumerate(files):
if i % step == 0:
print(f)
' "$ROOT/conformance/baseline.json" "$SAMPLE" "$R/runs")
flagged=0 checked=0
for f in "${FILES[@]}"; do
checked=$((checked + 1))
out=$(timeout "$TMO" "$H5RS" check -q "${DATA[@]}" "$C/$f" 2>&1)
rc=$?
if [ $rc -ne 0 ]; then
flagged=$((flagged + 1))
echo "== rc=$rc $f"
echo "$out" | head -5 | sed 's/^/ /'
fi
done
echo "== checked $checked ok files: $flagged flagged"
[ $flagged -eq 0 ]