Grammar-based, type-aware fuzzer for the Oberon-07 programming language.
fuzzberon generates random Oberon-07 modules by walking Wirth's EBNF
productions top-down. Unlike a purely syntactic generator, it threads a typed
symbol table through the walk, so the output is close to compilable and
exercises far more of a compiler front-end than token soup:
- identifiers are declared before use and reused by reference;
- record fields belong to their record type (no invented selectors);
- designators legally traverse arrays, records and pointers, with in-range index expressions;
- operators are applied to operands of the right type (
DIVon integers,/on reals and sets,&on booleans, ...); - procedure calls match the declared signature, including
VARparameters (which receive designators, not expressions); - proper procedures are called as statements, function procedures inside expressions of their result type;
FORcontrol variables are plainINTEGERvariables, array lengths are positive,CASElabels are distinct, hex literals start with a digit.
For negative testing of a type checker, --chaos P injects a wrong-typed
subexpression with probability P at every expression node.
No dependencies beyond Python 3.8+.
python3 oberon_fuzzer.py # one module to stdout
python3 oberon_fuzzer.py -n 5 --seed 42 # five reproducible modules
python3 oberon_fuzzer.py -d 6 # deeper statement nesting
python3 oberon_fuzzer.py --chaos 0.05 # sprinkle type errors
python3 oberon_fuzzer.py -n 100 -o out # write 100 .Mod files
python3 oberon_fuzzer.py --selftest 200 # sanity-check 200 seeds| Option | Description |
|---|---|
-n, --count N |
number of modules to generate (default: 1) |
--seed S |
base RNG seed; program i uses S + i |
-d, --max-depth D |
statement nesting budget (default: 4) |
--chaos P |
probability of a wrong-typed subexpression (default: 0) |
-o, --out-dir DIR |
write each module to a .Mod file in DIR |
--selftest N |
generate and structurally check N seeds, then exit |
MODULE Fuzz1824;
CONST
c1 = 8935;
c2 = c1 + 4;
TYPE
T3 = ARRAY 18 OF CHAR;
VAR
g4: INTEGER;
g8: SET;
v9*: BOOLEAN;
PROCEDURE P11();
BEGIN
IF (g4 > 0) & (g4 IN g8) THEN
FOR g4 := c2 * 7668 TO c1 DO
CASE g4 OF
91: INCL(g8, 23)
| 54: g4 := ABS(c2)
END
END
END
END P11;
BEGIN
P11()
END Fuzz1824.Each generator method in OberonFuzzer mirrors one production of the report
The Programming Language Oberon (revision 2016). A small structural type
model (Basic, Array, Record, Pointer, Named) backs a scoped symbol
table; expression generation dispatches on the requested type, and
leaf_paths enumerates every legal selector chain from a variable down to a
basic-typed component. Layout sentinels in the token stream drive a tiny
renderer that produces indented source.
from oberon_fuzzer import generate_program
src = generate_program(seed=42, max_depth=4, chaos=0.0)MIT