[Major Feature] Coverage-guided fuzz harness for Python API (libFuzzer + ASan) #283

Closed
opened 2026-03-08 03:19:59 +00:00 by john · 1 comment
Owner

Context

The 7DRL 2026 post-mortem found 22 memory safety bugs, most of which require specific input sequences to trigger (entity cross-grid transfer, holding references across mutations, etc.). The existing test suite exercises normal operation paths and misses these edge cases entirely — ASan found 0 bugs when run against the full test suite, but immediately found the gridstate overflow when given a targeted trigger.

Coverage-guided fuzzing would systematically explore these edge cases.

Proposal

Create tests/fuzz/ with Atheris-based fuzz targets:

  1. Grid/Entity fuzz target: Random sequences of grid creation, entity append/remove/transfer, position changes, visibility updates
  2. Collection fuzz target: Random insert/remove/slice operations on UICollection and UIEntityCollection
  3. Property fuzz target: Random get/set of properties on UI objects with varying types
  4. Animation fuzz target: Random animation creation, callback registration, stepping

Each target creates mcrfpy objects and performs random operations, letting ASan catch any memory corruption.

Prerequisites

  • Clang build (see #282)
  • Atheris pip package
  • ASan-instrumented build (make asan)
  • #258–#278 (the bugs fuzzing should find)
  • #279 (memory safety audit meta-issue)
## Context The 7DRL 2026 post-mortem found 22 memory safety bugs, most of which require specific input sequences to trigger (entity cross-grid transfer, holding references across mutations, etc.). The existing test suite exercises normal operation paths and misses these edge cases entirely — ASan found 0 bugs when run against the full test suite, but immediately found the gridstate overflow when given a targeted trigger. Coverage-guided fuzzing would systematically explore these edge cases. ## Proposal Create `tests/fuzz/` with Atheris-based fuzz targets: 1. **Grid/Entity fuzz target**: Random sequences of grid creation, entity append/remove/transfer, position changes, visibility updates 2. **Collection fuzz target**: Random insert/remove/slice operations on UICollection and UIEntityCollection 3. **Property fuzz target**: Random get/set of properties on UI objects with varying types 4. **Animation fuzz target**: Random animation creation, callback registration, stepping Each target creates mcrfpy objects and performs random operations, letting ASan catch any memory corruption. ## Prerequisites - Clang build (see #282) - Atheris pip package - ASan-instrumented build (`make asan`) ## Related - #258–#278 (the bugs fuzzing should find) - #279 (memory safety audit meta-issue)
Author
Owner

Closing. Resolution: shipped as a native clang+libFuzzer+ASan harness instead of Atheris. Python-level coverage would have added nothing — every bug from #258-#278 lives below the Python/C++ boundary and is reached through normal mcrfpy.* calls. libFuzzer already instruments the C++ engine code and drives input through a byte-consumer that the Python fuzz scripts read from; no atheris dependency was needed.

What shipped

  • make fuzz-build / make fuzz / make fuzz-long / make fuzz-repro (tranche W1)
  • build-fuzz/mcrfpy_fuzz single binary, target chosen by MCRF_FUZZ_TARGET env var (W2/W3)
  • Six Python-driven fuzz targets under tests/fuzz/:
    • fuzz_grid_entity — EntityCollection lifecycle (W4 → closed #258-#263, #273, #274)
    • fuzz_property_types — type confusion on Frame/Caption/Sprite/Entity/Grid/TileLayer/ColorLayer (W5 → closed #267, #268, #272)
    • fuzz_anim_timer_scene — animation/timer/scene lifecycle (W6)
    • fuzz_fovcompute_fov / is_in_fov with enum fuzzing (W8 → surfaced #310)
    • fuzz_maps_procgen — HeightMap/DiscreteMap/NoiseSource/BSP (W7)
    • fuzz_pathfinding_behavior — DijkstraMap, grid.step, entity behavior (W9 → surfaced #311)
  • README at tests/fuzz/README.md with triage workflow

Gaps intentionally left open (flagged for follow-up issues, not this one)

  • Tiled/LDtk import parsers (TileSetFile, TileMapFile, WangSet, LdtkProject, AutoRuleSet)
  • Shader / PropertyBinding / UniformCollection lifecycle
  • Audio DSP chain (SoundBuffer filters)
  • Texture factory methods (from_bytes, composite, hsl_shift)
  • Primitives not yet property-fuzzed (Line, Circle, Arc)

These represent new attack surface rather than gaps in the original proposal.

Closing. Resolution: **shipped as a native clang+libFuzzer+ASan harness instead of Atheris.** Python-level coverage would have added nothing — every bug from #258-#278 lives below the Python/C++ boundary and is reached through normal `mcrfpy.*` calls. libFuzzer already instruments the C++ engine code and drives input through a byte-consumer that the Python fuzz scripts read from; no `atheris` dependency was needed. ### What shipped - `make fuzz-build` / `make fuzz` / `make fuzz-long` / `make fuzz-repro` (tranche W1) - `build-fuzz/mcrfpy_fuzz` single binary, target chosen by `MCRF_FUZZ_TARGET` env var (W2/W3) - Six Python-driven fuzz targets under `tests/fuzz/`: - `fuzz_grid_entity` — EntityCollection lifecycle (W4 → closed #258-#263, #273, #274) - `fuzz_property_types` — type confusion on Frame/Caption/Sprite/Entity/Grid/TileLayer/ColorLayer (W5 → closed #267, #268, #272) - `fuzz_anim_timer_scene` — animation/timer/scene lifecycle (W6) - `fuzz_fov` — `compute_fov` / `is_in_fov` with enum fuzzing (W8 → surfaced #310) - `fuzz_maps_procgen` — HeightMap/DiscreteMap/NoiseSource/BSP (W7) - `fuzz_pathfinding_behavior` — DijkstraMap, `grid.step`, entity behavior (W9 → surfaced #311) - README at `tests/fuzz/README.md` with triage workflow ### Gaps intentionally left open (flagged for follow-up issues, not this one) - Tiled/LDtk import parsers (TileSetFile, TileMapFile, WangSet, LdtkProject, AutoRuleSet) - Shader / PropertyBinding / UniformCollection lifecycle - Audio DSP chain (SoundBuffer filters) - Texture factory methods (`from_bytes`, `composite`, `hsl_shift`) - Primitives not yet property-fuzzed (Line, Circle, Arc) These represent new attack surface rather than gaps in the original proposal.
john changed title from [Major Feature] Atheris coverage-guided fuzzing harness for Python API to [Major Feature] Coverage-guided fuzz harness for Python API (libFuzzer + ASan) 2026-04-17 03:15:00 +00:00
john closed this issue 2026-04-17 03:15:00 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
john/McRogueFace#283
No description provided.