Skip to content

Add a clang-oracle differential fuzzer and log 53 compiler bugs - #274

Open
gloveboxes wants to merge 14 commits into
mainfrom
test/clang-oracle-coverage
Open

gloveboxes wants to merge 14 commits into
mainfrom
test/clang-oracle-coverage

Conversation

@gloveboxes

Copy link
Copy Markdown
Collaborator

Summary

Differential-fuzzing campaign against the shipped compiler, using the local Apple clang as the oracle. Nothing here fixes a bug — this PR adds the tooling, the bug log, and a parked reproducer per bug so each one is checkable and tracked.

  • scripts/clang-oracle-fuzz.py with two generators: clang_oracle_gen.py (integer/pointer/struct) and clang_oracle_float_gen.py (float). Each generated program is proven on the host (clang -O0/-O2 plus an ASan/UBSan build must agree), then compiled with dcc in every production configuration (peep/nopeep × stack check) and run under ntvcm. Mismatches are auto-reduced; the generators steer round logged shapes so new bugs keep surfacing. See scripts/README.md.
  • compiler-bugs.md: the log. 53 bugs (BUG-002–BUG-053), 51 open (32 wrong results, the rest rejections/crashes/silent bad code); 4 need dccpeep, the rest reproduce with and without it. Each has a GitHub issue (Wrong code: unsigned char local <<= an unsigned char variable is not truncated to 8 bits on return #223–Wrong code (dccpeep): assigned 32-bit parameter read through a pointer after an empty loop returns the old value (pass_elim_dead_ix_stores forgets the escape at an LS label) #273) and many have facet comments as further shapes were found.
  • tests/known-bugs/bugNNN.c + baselines/: one minimal host-proven reproducer per open bug. python3 scripts/run-known-bugs.py reports fails/FIXED for each (currently 51/51 fail). These are deliberately not in the regression suite, so the suite stays green; flip one into tests/ when its bug is fixed.
  • New suite tests tests/tcastasg.c, tests/twcasgm.c (generated programs that pass today, promoted to lock in behaviour).

Validation

  • python3 ./scripts/runall.py -mode=full -extended → SUCCESS
  • python3 scripts/run-known-bugs.py → 51 reproducers: 51 fails
  • Float campaign stop rule met: two consecutive clean 300-seed batches after the last steering change (seeds 5041–5640).

Notes for review

  • Compiler under test is upstream main at 83dc7a91; the branch is rebased on current main.
  • Forced-MIR-candidate runs (--configs all) are in progress separately and will be a follow-up.

gloveboxes and others added 14 commits November 13, 2026 13:06
scripts/clang-oracle-fuzz.py generates whole C programs (statements, loops,
switches, nested-block locals, structs, bit-fields, pointers, calls) and
compares dcc's output with the host compiler's. The source is the same for
both compilers: it uses fixed-width types only, the renderer inserts the
casts that make it mean the same with a 16-bit int, and a host-only checked
build under ASan and UBSan rejects any program whose result could
legitimately differ. It also reduces a failing program to a small one.

compiler-bugs.md logs what it found at 83dc7a9: 19 open defects in the
shipped configuration (9 wrong results, 1 hang, 9 rejections of valid C),
each filed upstream as #223-#241. Nothing is fixed here.

tests/known-bugs/ holds one reproducer per open entry with a baseline
taken from clang; scripts/run-known-bugs.py proves each baseline with the
host compiler and reports whether dcc still fails it. They are outside
tests/*.c, so the regression suite is unaffected.

Three new suite tests cover shapes that upstream fixed in 34e35b3 while
this was in progress: twcasgm (32-bit value compound-assigned to a narrower
member, element or pointer target), tblkdiv (32-bit member divided by a
nested-block 16-bit local) and tcastasg (narrowing cast of an assignment's
value). Their baselines are clang's output.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Eight more defects found by differential fuzzing against clang, each with a
reproducer in tests/known-bugs/ whose baseline is clang's output, an entry
in compiler-bugs.md and an upstream issue (#242-#249). BUG-004, 006, 012,
019 and 025 gain the further shapes found since.

Fuzzer:
- the host lint also rejects C23-only syntax, and the renderer no longer
  ends a switch on a bare case label;
- a program that does not fit in 64K or in the TPA is a target limit, not
  a failure;
- known_shapes() no longer reports loop counter steps or constants, so the
  reducer's guard against sliding into a logged bug is effective, and a
  program whose repair rebuilt a logged shape is dropped;
- new avoidance features for BUG-019, 023 and 025-029.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Four more defects from the clang-oracle fuzzer, each with a reproducer in
tests/known-bugs/ proven by clang, a compiler-bugs.md entry and an upstream
issue (#250-#253): a for-init declaration that shares a stack slot with its
enclosing block's locals, a nested-block 32-bit local stored with only its
low byte, a dccpeep pass that drops an add, and a rejected constant
division by zero. BUG-015, 016 and 030 gain further shapes.

The generator steers round the new shapes, and around returns of a
nested-block object to a 32-bit type (BUG-025).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
dccpeep turns `8 == v` into a test of bit 3 (upstream issue #254). Unary
operators over a folded constant expression are rejected in more forms
than BUG-012 listed; the generator now steers round all of them.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
dccpeep's preserve_ix_word_signed_range compares a 16-bit local with itself
(upstream issue #255). A nested-block uint16_t pointer is shifted and divided
as signed (BUG-015), a constant-initialised nested-block local assigned from
another local loses its high byte (BUG-031), and a dccpeep add can feed a
helper call (BUG-032). The generator avoids all four, and the fuzzer counts
an image the emulator cannot load as a target limit.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…, and steer the fuzzer

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nd shape

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…uzzer

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
A float-typed program generator for clang-oracle-fuzz.py (--gen float),
with repair, known-shape steering and per-expression sequencing so clang
does not reject generated programs as unsequenced. Reproducers and
baselines for BUG-039..053 under tests/known-bugs, and facets of
BUG-015, 016, 019, 020, 026, 036 and 050 in compiler-bugs.md.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Widen the float generator's steering so a 32-bit parameter arm of a ?:
and a ?: over nested-block floats no longer regenerate known bugs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add the appendix page describing the clang-oracle fuzzing method, the
tools in scripts/ and the campaign and bug-logging workflow, with the
clang-oracle-testing.svg diagram. Move the issue-body generator into
scripts/ with titles and issue links taken from compiler-bugs.md.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nd 20149

Forced-MIR-candidate runs (21 nopeep configs, seeds 20001-20300, int and
float) found no candidate-only failures. The two production-visible
failures are new facets of existing bugs; steer the generators around them.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@gloveboxes

Copy link
Copy Markdown
Collaborator Author

Forced-MIR-candidate runs (DCC_MIR_SELECT_CANDIDATE/DCC_MIR_PREFER_REGIONAL/DCC_MIR_NO_EXACT — 19 forced candidates + nopeep + noexact-nopeep), seeds 20001–20300, integer and float generators:

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant