AtlatestRepositorysigil-vt
1
#!/usr/bin/env bash2
# M2 GATE: build + run the sigil-vt fuzz driver under the sanitizers.3
# The pure C core (native/vt.c under -DVT_FUZZ) is standalone — no libsigil.4
#5
# RUN IT LIKE THIS (compiler AND runtime must both come from the manifest):6
#7
# guix shell -m ../sigil/manifest.scm -- spike/fuzz.sh8
#9
# The monorepo manifest already carries gcc-toolchain, whose ASan is REAL.10
# Two ways to end up with a silently blind gate — both caught by the self-test11
# below, neither obvious from the output:12
#13
# 1. THE PINNED ZIG HAS NO ASan RUNTIME. `zig cc -fsanitize=address` alone14
# fails to link (undefined __asan_report_load4); with `address,undefined`15
# it links and SILENTLY DROPS ASan (zero __asan symbols in the binary) and16
# still prints FUZZ CLEAN. gcc keeps ASan with the same flag combo — the17
# silent drop is zig-specific. Do not use zig for this gate.18
# 2. RUNNING OUTSIDE THE GUIX SHELL. The same gcc-built binary does NOT fault19
# when run outside the shell — it exits cleanly, looking exactly like a20
# pass. Compile AND run inside.21
#22
# This is not hypothetical: a real heap over-read (t-d4c7) shipped through23
# 5,000,000 "clean" iterations of this gate.24
set -euo pipefail25
cd "$(dirname "$0")/.."26
CC="${CC:-gcc}"27
ITERS="${1:-3000000}"28
SAN_FLAGS="-fsanitize=address,undefined -fno-sanitize-recover=all"29
mkdir -p build31
# ---------------------------------------------------------------------------32
# STEP 0 — PROVE THE GATE CAN FIRE, BEFORE TRUSTING ANYTHING IT SAYS.33
# Compile a KNOWN heap over-read with the SAME compiler and flags, and require34
# it to be caught. A gate that cannot demonstrate it fires is not a gate. This35
# check covers BOTH failure modes above without having to detect either.36
# ---------------------------------------------------------------------------37
echo "== sanitizer self-test (can this build detect a heap over-read?) =="38
"$CC" -std=c99 -O1 -g $SAN_FLAGS spike/sanitizer-selftest.c -o build/san-selftest39
set +e40
san_out="$(ASAN_OPTIONS=abort_on_error=1 UBSAN_OPTIONS=halt_on_error=1 \41
./build/san-selftest 2>&1)"42
rc=$?43
set -e44
# Match the DIAGNOSTIC, not the exit code. A caught over-read ABORTS (SIGABRT,45
# rc 134) — it can never exit 0 — while a bare non-zero exit could just mean the46
# binary failed to launch. Only an actual ASan report proves the gate fired.47
if printf '%s' "$san_out" | grep -qE "AddressSanitizer.*(heap-buffer-overflow|SEGV)"; then48
echo " ok: a 1456-byte heap over-read was caught — sanitizer is real."49
elif [ "$rc" -eq 1 ]; then50
cat >&2 <<'MSG'52
SANITIZER SELF-TEST FAILED — THIS BUILD IS BLIND.54
A deliberate 1456-byte heap over-read was NOT detected, so this build has no55
working AddressSanitizer. Any "FUZZ CLEAN" from it is meaningless: it cannot56
see heap-buffer-overflow, use-after-free, or leaks — the exact bug classes57
this gate exists to catch (the parser consumes UNTRUSTED pty bytes).59
This is how the t-d4c7 scrollback over-read shipped through 5,000,00060
"clean" iterations.62
Almost always one of:63
1. you used zig -> it has no ASan runtime and drops it silently64
2. you ran OUTSIDE the guix shell -> the runtime never engages66
Fix by running the whole thing inside the manifest shell:67
guix shell -m ../sigil/manifest.scm -- spike/fuzz.sh69
Do NOT silence this check.71
If you only want the UBSan coverage (which IS real — it caught the CSI param72
int overflow), run: SAN_UBSAN_ONLY=1 spike/fuzz.sh73
That is NOT the M2 memory-safety gate and must never be reported as one.74
MSG75
if [ "${SAN_UBSAN_ONLY:-0}" = "1" ]; then76
echo "" >&277
echo " SAN_UBSAN_ONLY=1 set — continuing WITHOUT memory-safety coverage." >&278
echo " This run CANNOT satisfy the M2 gate. Report it as UBSAN-ONLY." >&279
echo "" >&280
UBSAN_ONLY=181
else82
exit 183
fi84
else85
echo " self-test exited $rc with no AddressSanitizer diagnostic." >&286
echo " That is neither a clean catch nor a clean miss — refusing to guess." >&287
printf '%s\n' "$san_out" | head -5 >&288
exit 189
fi91
echo "== compiling vt-fuzz =="92
"$CC" -std=c99 -O1 -g -DVT_FUZZ \93
-Wall -Wextra -Wno-unused-parameter \94
$SAN_FLAGS \95
native/vt-fuzz.c -o build/vt-fuzz96
echo "== running $ITERS iterations =="97
ASAN_OPTIONS=detect_leaks=1:abort_on_error=1 \98
UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1 \99
./build/vt-fuzz "$ITERS"101
if [ "${UBSAN_ONLY:-0}" = "1" ]; then102
cat >&2 <<'MSG'104
^ UBSAN-ONLY RUN. This did NOT check memory safety (no working ASan).105
It does not satisfy the M2 gate. Do not record it as "ASan/UBSan clean".106
MSG107
fi