Skip to content

Commit 4ecc4c8

Browse files
copyleftdevclaude
andauthored
feat: Fuzz Infrastructure Setup (TASK-500) (#98)
Comprehensive fuzz testing infrastructure for parser robustness: - Created 4 new fuzz test files for HTTP/1.1, HTTP/2, HPACK, and Scenario parsers - Added 60+ corpus seed files across 5 target directories (http1_response, http2_frame, hpack, scenario, event) - Implemented fuzz-targets build step in build.zig - Added scripts/run-fuzz.sh for running fuzz tests - Added scripts/minimize-corpus.sh for corpus management (placeholder) - Fixed parser assertions that caused crashes during fuzzing: - HPACK decodeString: removed assertion, use error return for empty input - HTTP/2 parseHeader: moved assertion after input validation - Exported HTTP2_MAX_FRAME_SIZE constant from z6.zig Test results: - HPACK decoder: 6/6 tests pass, 1M iterations - HTTP/2 frame: 5/5 tests pass, 1M iterations Note: HTTP/1.1, Scenario, and Event fuzz tests have pre-existing Zig 0.14 API compatibility issues (ArrayList.deinit signature) in the main codebase that need separate fixes. Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 09b861d commit 4ecc4c8

70 files changed

Lines changed: 1506 additions & 15 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

build.zig

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -428,12 +428,63 @@ pub fn build(b: *std.Build) void {
428428
test_step.dependOn(&run_checker_tests.step);
429429
test_step.dependOn(&run_loop_tests.step);
430430

431-
// Fuzz targets (placeholder for TASK-300+)
432-
_ = b.step("fuzz-targets", "Build all fuzz targets");
433-
// TODO: Add fuzz targets when parsers are implemented:
434-
// - fuzz_http1_response
435-
// - fuzz_http2_frame
436-
// - fuzz_event_serialization
431+
// Fuzz targets (TASK-500)
432+
const fuzz_step = b.step("fuzz-targets", "Build and run all fuzz targets");
433+
434+
// HTTP/1.1 Parser fuzz tests
435+
const http1_fuzz = b.addTest(.{
436+
.name = "http1_parser_fuzz",
437+
.root_source_file = b.path("tests/fuzz/http1_parser_fuzz.zig"),
438+
.target = target,
439+
.optimize = optimize,
440+
});
441+
http1_fuzz.root_module.addImport("z6", z6_module);
442+
const run_http1_fuzz = b.addRunArtifact(http1_fuzz);
443+
fuzz_step.dependOn(&run_http1_fuzz.step);
444+
445+
// HTTP/2 Frame Parser fuzz tests
446+
const http2_fuzz = b.addTest(.{
447+
.name = "http2_frame_fuzz",
448+
.root_source_file = b.path("tests/fuzz/http2_frame_fuzz.zig"),
449+
.target = target,
450+
.optimize = optimize,
451+
});
452+
http2_fuzz.root_module.addImport("z6", z6_module);
453+
const run_http2_fuzz = b.addRunArtifact(http2_fuzz);
454+
fuzz_step.dependOn(&run_http2_fuzz.step);
455+
456+
// HPACK Decoder fuzz tests
457+
const hpack_fuzz = b.addTest(.{
458+
.name = "hpack_decoder_fuzz",
459+
.root_source_file = b.path("tests/fuzz/hpack_decoder_fuzz.zig"),
460+
.target = target,
461+
.optimize = optimize,
462+
});
463+
hpack_fuzz.root_module.addImport("z6", z6_module);
464+
const run_hpack_fuzz = b.addRunArtifact(hpack_fuzz);
465+
fuzz_step.dependOn(&run_hpack_fuzz.step);
466+
467+
// Scenario Parser fuzz tests
468+
const scenario_fuzz = b.addTest(.{
469+
.name = "scenario_parser_fuzz",
470+
.root_source_file = b.path("tests/fuzz/scenario_parser_fuzz.zig"),
471+
.target = target,
472+
.optimize = optimize,
473+
});
474+
scenario_fuzz.root_module.addImport("z6", z6_module);
475+
const run_scenario_fuzz = b.addRunArtifact(scenario_fuzz);
476+
fuzz_step.dependOn(&run_scenario_fuzz.step);
477+
478+
// Event Serialization fuzz tests (existing)
479+
const event_fuzz = b.addTest(.{
480+
.name = "event_serialization_fuzz",
481+
.root_source_file = b.path("tests/fuzz/event_serialization_fuzz.zig"),
482+
.target = target,
483+
.optimize = optimize,
484+
});
485+
event_fuzz.root_module.addImport("z6", z6_module);
486+
const run_event_fuzz = b.addRunArtifact(event_fuzz);
487+
fuzz_step.dependOn(&run_event_fuzz.step);
437488

438489
// Documentation generation (placeholder for TASK-400+)
439490
_ = b.step("docs", "Generate documentation");

corpus/event/empty.bin

Whitespace-only changes.

corpus/event/random.bin

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
��+�Gò�L�4���)$ �hK� ܤ2��a�\(�ٱ&%�=="S�Ū$=�tG���&�O ,?�"+��1� �Lq�@fT��~��d�C�J<�����s����q/~jgBv������4�|�9.,�L#ư�(F@��kZ!�Tk?F�GI�QNƳ�M*t�<�e�H40 ՞�ݟ̊+�۳?u�@��6 뉖~W_��A;��ʙKV��M�
2+
ۧI�1���/C�þ��[P��0�!r ���+�- ��C)���?�)�

corpus/event/too_long.bin

500 Bytes
Binary file not shown.

corpus/event/truncated.bin

100 Bytes
Binary file not shown.

corpus/event/zeros.bin

272 Bytes
Binary file not shown.

corpus/hpack/empty.bin

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

corpus/hpack/indexed_multi.bin

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
���
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

0 commit comments

Comments
 (0)