Skip to content

Commit 58f9288

Browse files
authored
Merge pull request #22862 from ziglang/fuzz
fuzzer: write inputs to shared memory before running
2 parents db0d9c2 + d789f1e commit 58f9288

File tree

6 files changed

+346
-209
lines changed

6 files changed

+346
-209
lines changed

lib/compiler/test_runner.zig

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ fn mainServer() !void {
150150
try server.serveU64Message(.fuzz_start_addr, entry_addr);
151151
defer if (testing.allocator_instance.deinit() == .leak) std.process.exit(1);
152152
is_fuzz_test = false;
153+
fuzzer_set_name(test_fn.name.ptr, test_fn.name.len);
153154
test_fn.func() catch |err| switch (err) {
154155
error.SkipZigTest => return,
155156
else => {
@@ -341,12 +342,15 @@ const FuzzerSlice = extern struct {
341342

342343
var is_fuzz_test: bool = undefined;
343344

344-
extern fn fuzzer_start(testOne: *const fn ([*]const u8, usize) callconv(.C) void) void;
345+
extern fn fuzzer_set_name(name_ptr: [*]const u8, name_len: usize) void;
345346
extern fn fuzzer_init(cache_dir: FuzzerSlice) void;
347+
extern fn fuzzer_init_corpus_elem(input_ptr: [*]const u8, input_len: usize) void;
348+
extern fn fuzzer_start(testOne: *const fn ([*]const u8, usize) callconv(.C) void) void;
346349
extern fn fuzzer_coverage_id() u64;
347350

348351
pub fn fuzz(
349-
comptime testOne: fn ([]const u8) anyerror!void,
352+
context: anytype,
353+
comptime testOne: fn (context: @TypeOf(context), []const u8) anyerror!void,
350354
options: testing.FuzzInputOptions,
351355
) anyerror!void {
352356
// Prevent this function from confusing the fuzzer by omitting its own code
@@ -371,12 +375,14 @@ pub fn fuzz(
371375
// our standard unit test checks such as memory leaks, and interaction with
372376
// error logs.
373377
const global = struct {
378+
var ctx: @TypeOf(context) = undefined;
379+
374380
fn fuzzer_one(input_ptr: [*]const u8, input_len: usize) callconv(.C) void {
375381
@disableInstrumentation();
376382
testing.allocator_instance = .{};
377383
defer if (testing.allocator_instance.deinit() == .leak) std.process.exit(1);
378384
log_err_count = 0;
379-
testOne(input_ptr[0..input_len]) catch |err| switch (err) {
385+
testOne(ctx, input_ptr[0..input_len]) catch |err| switch (err) {
380386
error.SkipZigTest => return,
381387
else => {
382388
std.debug.lockStdErr();
@@ -395,18 +401,22 @@ pub fn fuzz(
395401
if (builtin.fuzz) {
396402
const prev_allocator_state = testing.allocator_instance;
397403
testing.allocator_instance = .{};
404+
defer testing.allocator_instance = prev_allocator_state;
405+
406+
for (options.corpus) |elem| fuzzer_init_corpus_elem(elem.ptr, elem.len);
407+
408+
global.ctx = context;
398409
fuzzer_start(&global.fuzzer_one);
399-
testing.allocator_instance = prev_allocator_state;
400410
return;
401411
}
402412

403413
// When the unit test executable is not built in fuzz mode, only run the
404414
// provided corpus.
405415
for (options.corpus) |input| {
406-
try testOne(input);
416+
try testOne(context, input);
407417
}
408418

409419
// In case there is no provided corpus, also use an empty
410420
// string as a smoke test.
411-
try testOne("");
421+
try testOne(context, "");
412422
}

0 commit comments

Comments
 (0)