← board

pasmith emits order-dependent programs, and its printed repro line does not reproduce

Defect 1 — the repro: line in every report is INCOMPLETE, so it does not reproduce

Reports print:

repro: tools/pasmith.py --seed N --vars 10 --funcs 3 --stmts 20 --depth 3

but twatch.py actually launches the fuzzer with --classes 4 --strs 3 as well. Running the printed line generates a different program, which does not diverge — so anyone triaging a report by hand concludes "cannot reproduce" and the finding is discarded.

The working line is:

tools/pasmith.py --seed N --vars 10 --funcs 3 --stmts 20 --depth 3 --classes 4 --objs 3 --strs 3

pasmith_run.py builds the repro string and omits --classes/--objs/--strs. One-line fix: print the ACTUAL argv it ran with, never a hand-written subset. A repro line that does not reproduce is worse than no repro line.

Defect 2 — the generator emits programs whose result depends on evaluation ORDER

~3% of the divergences (3 of a 40-seed sample: 3384, 7704, 9565) are not compiler bugs. The generator puts two side-effecting calls in one argument list / operand pair:

g7 := SafeMod_qword(qword(not f1(g14)), qword(g7 and f0(g6, g6)));

Pascal leaves argument evaluation order unspecified. pxx evaluates call arguments left-to-right, FPC right-to-left; both are legal. Since every generated function calls the checksum Mix(), the two orders produce the same multiset of mixed values in a different ORDER, and the checksum differs.

This is category (a) in the fuzzer's own report note ("pasmith emitted UB/impl-defined code"). Filing it against Track A would be wrong.

Fix options (pick one):

Why both matter more than they look

Together they set the false-signal rate of the whole fuzzing lane: defect 2 manufactures divergences that are not bugs, and defect 1 makes every report — real or not — unverifiable by hand.

Gate

tools/testmgr.py --tier full green; a report's printed repro line, pasted verbatim, reproduces the divergence.

Defect 3 (found while fixing 1 and 2) — the fuzzer tested the PINNED binary, not the sha

pasmith_run.py defaulted its compiler to PXX_STABLE = stable_linux_amd64/default/pinned — the committed pin, which lags HEAD by however many commits. So the idle fuzz slice ran against a compiler from long before the sha it stamped on every finding. Two consequences:

Proof: the 81 seeds that diverged against the pin give 0 divergences against the compiler built at HEAD.

Fix: prefer the locally built compiler/pascal26 (what testmgr built at this sha); fall back to the pin only when there is no local build; PXX_STABLE still overrides for deliberately fuzzing the pin. Every report now records compiler=<path> — a finding that does not say which binary produced it cannot be attributed at all.

Resolution (2026-07-14)

All three defects fixed.

Log