mirror of
https://github.com/bdbrown4/peltier.io.git
synced 2026-11-07 10:58:28 +00:00
agent: comrak diff-fuzzer for the phase2-comrak-010 audit
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EcKPWQ3MQD4NdEHwar96u2
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,90 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Differential fuzz for comrak attempts: pristine vs candidate must
|
||||||
|
produce byte-identical HTML (stdout), stderr, and exit code on mutated
|
||||||
|
markdown. comrak is a single-threaded stdin->stdout filter, so raw byte
|
||||||
|
comparison needs no canonicalization.
|
||||||
|
|
||||||
|
python3 scripts/diff-fuzz-comrak.py <workdir> <iters> <candidate-bin>
|
||||||
|
|
||||||
|
Seeds: windows of the pinned Pro Git corpus. Mutations focus on inline/
|
||||||
|
block structure the parser and teardown paths exercise: emphasis, code
|
||||||
|
fences, links, HTML blocks, list markers, plus raw byte noise.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import random
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path("/home/user/peltier.io")
|
||||||
|
BASE = ROOT / "targets/comrak/baseline/release/comrak"
|
||||||
|
CAND = ROOT / sys.argv[3]
|
||||||
|
CORPUS = ROOT / "corpora/comrak/progit.md"
|
||||||
|
WORK = Path(sys.argv[1])
|
||||||
|
ITERS = int(sys.argv[2])
|
||||||
|
|
||||||
|
TOKENS = [
|
||||||
|
b"**", b"*", b"__", b"_", b"`", b"```", b"~~~", b"~~", b"[", b"](", b")",
|
||||||
|
b"![", b"#", b"##", b">", b"- ", b"1. ", b"|", b"---", b"<div>", b"</div>",
|
||||||
|
b"<!--", b"-->", b"\\", b"&", b"<http://x>", b" ", b"\t",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def mutate(data: bytes, rng: random.Random) -> bytes:
|
||||||
|
b = bytearray(data)
|
||||||
|
for _ in range(rng.randrange(1, 8)):
|
||||||
|
if not b:
|
||||||
|
b = bytearray(rng.choice(TOKENS))
|
||||||
|
continue
|
||||||
|
op = rng.randrange(5)
|
||||||
|
pos = rng.randrange(len(b) + 1)
|
||||||
|
if op == 0:
|
||||||
|
b[pos:pos] = rng.choice(TOKENS)
|
||||||
|
elif op == 1 and len(b) > 2:
|
||||||
|
del b[pos:min(len(b), pos + rng.randrange(1, 16))]
|
||||||
|
elif op == 2 and pos < len(b):
|
||||||
|
b[pos] = rng.randrange(256)
|
||||||
|
elif op == 3:
|
||||||
|
end = min(len(b), pos + rng.randrange(1, 64))
|
||||||
|
b[end:end] = b[pos:end]
|
||||||
|
else:
|
||||||
|
b[pos:pos] = b"\n\n"
|
||||||
|
return bytes(b)
|
||||||
|
|
||||||
|
|
||||||
|
def run(binary: Path, payload: bytes) -> tuple[bytes, bytes, int]:
|
||||||
|
r = subprocess.run([str(binary)], input=payload, capture_output=True, timeout=60)
|
||||||
|
return r.stdout, r.stderr, r.returncode
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
rng = random.Random(0xC0FFEE)
|
||||||
|
corpus = CORPUS.read_bytes()
|
||||||
|
# Seed windows across the whole book, varied sizes.
|
||||||
|
seeds = [
|
||||||
|
corpus[o : o + n]
|
||||||
|
for o in range(0, len(corpus) - 65536, len(corpus) // 300)
|
||||||
|
for n in (512, 4096, 32768)
|
||||||
|
]
|
||||||
|
WORK.mkdir(parents=True, exist_ok=True)
|
||||||
|
divergences = 0
|
||||||
|
for i in range(ITERS):
|
||||||
|
payload = mutate(rng.choice(seeds), rng)
|
||||||
|
a = run(BASE, payload)
|
||||||
|
b = run(CAND, payload)
|
||||||
|
if a != b:
|
||||||
|
divergences += 1
|
||||||
|
keep = WORK / f"divergence-{i}"
|
||||||
|
keep.mkdir()
|
||||||
|
(keep / "input.md").write_bytes(payload)
|
||||||
|
(keep / "baseline.out").write_bytes(a[0] + b"\n--stderr--\n" + a[1] + f"\nrc={a[2]}".encode())
|
||||||
|
(keep / "candidate.out").write_bytes(b[0] + b"\n--stderr--\n" + b[1] + f"\nrc={b[2]}".encode())
|
||||||
|
print(f"DIVERGENCE at iter {i}; kept in {keep}")
|
||||||
|
if (i + 1) % 1000 == 0:
|
||||||
|
print(f"{i + 1}/{ITERS}, {divergences} divergences", flush=True)
|
||||||
|
print(f"done: {ITERS} inputs, {divergences} divergences")
|
||||||
|
return 1 if divergences else 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
Reference in New Issue
Block a user