Fuzz Testing
debt(d7/e5/b3/t7)
Closest to 'only careful code review or runtime testing' (d7). The absence of fuzz testing is not caught by compilers, linters, or standard static analysis — tools like php-fuzzer, afl, libfuzzer, and atheris (listed in detection_hints.tools) must be deliberately set up and run. The gap is invisible until someone audits the test strategy or a production incident reveals an untested malformed input path.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix points to adding fuzzer coverage to input parsers and file upload handlers, but actually doing this requires setting up a fuzzing harness, building a valid input corpus, configuring the fuzzer toolchain (php-fuzzer, afl, etc.), and integrating it into CI — not a one-line patch. It touches multiple handlers and requires ongoing investment (per common_mistakes: not running long enough, needing minimised repro cases, corpus management).
Closest to 'localised tax' (b3). Fuzz testing is an additive testing practice. Once set up, the burden is contained to the testing infrastructure and the specific input-handling components targeted. The rest of the codebase is unaffected; it doesn't reshape architecture or impose a persistent tax on all work streams.
Closest to 'serious trap — contradicts how a similar concept works elsewhere' (t7). The canonical misconception is explicit in the term's metadata: developers assume fuzzing is only for low-level C/C++ security research (AFL, libFuzzer on native code), and therefore skip it entirely for PHP. This contradicts the reality that PHP applications parsing user-controlled XML, JSON, file uploads, and URL parameters are prime fuzzing targets. A competent developer familiar with C fuzzing but new to PHP web contexts will systematically underestimate the applicability and leave critical input paths untested.
Also Known As
TL;DR
Explanation
Fuzzing sends unexpected input: very long strings, null bytes, Unicode edge cases, negative numbers where positive is expected, malformed JSON, and boundary-crossing values. Coverage-guided fuzzers (American Fuzzy Lop, libFuzzer) track which code paths are covered and generate inputs to explore uncovered paths. For PHP: Paraunit, php-fuzzer, or manual property-based testing with Eris. Fuzzing is essential for parsers, decoders, file processors, and any code accepting external input. It finds bugs that would take years of production traffic to surface naturally.
Common Misconception
Why It Matters
Common Mistakes
- Not running fuzz testing long enough — many bugs only appear after millions of iterations.
- Fuzzing without a corpus of valid inputs — fuzzers starting from valid inputs find more coverage faster.
- Not capturing minimised repro cases — fuzzers should shrink failing inputs to the minimal reproducing case.
- Fuzzing only the happy path inputs — the value of fuzzing is in the unexpected and malformed.
Code Examples
// Parser with no fuzz testing — crashes in production:
function parseCustomFormat(string $input): array {
// Assumes: well-formed input, ASCII only, max 1000 chars
// Production receives: 50KB Unicode string with null bytes
// Result: Fatal error, memory exhaustion, or security bypass
$parts = explode(':', $input);
return ['key' => $parts[0], 'value' => $parts[1]]; // Undefined offset!
}
// Property-based fuzzing with Eris:
use Eris\Generator;
public function testParserHandlesArbitraryInput(): void {
$this->forAll(
Generator\string() // Random strings of any content
)->then(function(string $input) {
// Should never throw or crash:
$result = parseCustomFormat($input);
$this->assertIsArray($result); // Must always return array
});
}
// Runs hundreds of random inputs, shrinks failures to minimal case