| ... | @@ -17,12 +17,7 @@ fn logOverride( | ... | @@ -17,12 +17,7 @@ fn logOverride( |
| 17 | comptime format: []const u8, | 17 | comptime format: []const u8, |
| 18 | args: anytype, | 18 | args: anytype, |
| 19 | ) void { | 19 | ) void { |
| 20 | const f = if (log_file) |f| f else f: { | 20 | const f = if (log_file) |f| f else return; |
| 21 | const f = fuzzer.cache_dir.createFile("tmp/libfuzzer.log", .{}) catch | | |
| 22 | @panic("failed to open fuzzer log file"); | | |
| 23 | log_file = f; | | |
| 24 | break :f f; | | |
| 25 | }; | | |
| 26 | const prefix1 = comptime level.asText(); | 21 | const prefix1 = comptime level.asText(); |
| 27 | const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; | 22 | const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; |
| 28 | f.writer().print(prefix1 ++ prefix2 ++ format ++ "\n", args) catch @panic("failed to write to fuzzer log"); | 23 | f.writer().print(prefix1 ++ prefix2 ++ format ++ "\n", args) catch @panic("failed to write to fuzzer log"); |
| ... | @@ -98,10 +93,11 @@ export fn __sanitizer_cov_pcs_init(start: usize, end: usize) void { | ... | @@ -98,10 +93,11 @@ export fn __sanitizer_cov_pcs_init(start: usize, end: usize) void { |
| 98 | | 93 | |
| 99 | fn handleCmp(pc: usize, arg1: u64, arg2: u64) void { | 94 | fn handleCmp(pc: usize, arg1: u64, arg2: u64) void { |
| 100 | fuzzer.traceValue(pc ^ arg1 ^ arg2); | 95 | fuzzer.traceValue(pc ^ arg1 ^ arg2); |
| 101 | //std.log.debug("0x{x}: comparison of {d} and {d}", .{ pc, arg1, arg2 }); | 96 | // std.log.debug("0x{x}: comparison of {d} and {d}", .{ pc, arg1, arg2 }); |
| 102 | } | 97 | } |
| 103 | | 98 | |
| 104 | const Fuzzer = struct { | 99 | const Fuzzer = struct { |
| | 100 | inited: bool = false, |
| 105 | rng: std.Random.DefaultPrng, | 101 | rng: std.Random.DefaultPrng, |
| 106 | pcs: []const usize, | 102 | pcs: []const usize, |
| 107 | pc_counters: []u8, | 103 | pc_counters: []u8, |
| ... | @@ -157,6 +153,9 @@ const Fuzzer = struct { | ... | @@ -157,6 +153,9 @@ const Fuzzer = struct { |
| 157 | f.pc_counters = pc_counters; | 153 | f.pc_counters = pc_counters; |
| 158 | f.pcs = pcs; | 154 | f.pcs = pcs; |
| 159 | | 155 | |
| | 156 | log_file = fuzzer.cache_dir.createFile("tmp/libfuzzer.log", .{}) catch |
| | 157 | @panic("failed to open fuzzer log file"); |
| | 158 | |
| 160 | // Choose a file name for the coverage based on a hash of the PCs that will be stored within. | 159 | // Choose a file name for the coverage based on a hash of the PCs that will be stored within. |
| 161 | const pc_digest = std.hash.Wyhash.hash(0, std.mem.sliceAsBytes(pcs)); | 160 | const pc_digest = std.hash.Wyhash.hash(0, std.mem.sliceAsBytes(pcs)); |
| 162 | f.coverage_id = pc_digest; | 161 | f.coverage_id = pc_digest; |
| ... | @@ -210,6 +209,8 @@ const Fuzzer = struct { | ... | @@ -210,6 +209,8 @@ const Fuzzer = struct { |
| 210 | f.seen_pcs.appendNTimesAssumeCapacity(0, n_bitset_elems * @sizeOf(usize)); | 209 | f.seen_pcs.appendNTimesAssumeCapacity(0, n_bitset_elems * @sizeOf(usize)); |
| 211 | f.seen_pcs.appendSliceAssumeCapacity(std.mem.sliceAsBytes(pcs)); | 210 | f.seen_pcs.appendSliceAssumeCapacity(std.mem.sliceAsBytes(pcs)); |
| 212 | } | 211 | } |
| | 212 | |
| | 213 | f.inited = true; |
| 213 | } | 214 | } |
| 214 | | 215 | |
| 215 | fn initNextInput(f: *Fuzzer) void { | 216 | fn initNextInput(f: *Fuzzer) void { |
| ... | @@ -296,7 +297,9 @@ const Fuzzer = struct { | ... | @@ -296,7 +297,9 @@ const Fuzzer = struct { |
| 296 | /// where it branches. | 297 | /// where it branches. |
| 297 | fn traceValue(f: *Fuzzer, x: usize) void { | 298 | fn traceValue(f: *Fuzzer, x: usize) void { |
| 298 | errdefer |err| oom(err); | 299 | errdefer |err| oom(err); |
| 299 | try f.traced_comparisons.put(gpa, x, {}); | 300 | if (f.inited) { |
| | 301 | try f.traced_comparisons.put(gpa, x, {}); |
| | 302 | } |
| 300 | } | 303 | } |
| 301 | | 304 | |
| 302 | const Mutation = enum { | 305 | const Mutation = enum { |
| ... | @@ -310,19 +313,21 @@ const Fuzzer = struct { | ... | @@ -310,19 +313,21 @@ const Fuzzer = struct { |
| 310 | f.input.clearRetainingCapacity(); | 313 | f.input.clearRetainingCapacity(); |
| 311 | const old_input = f.corpus.items[corpus_index].bytes; | 314 | const old_input = f.corpus.items[corpus_index].bytes; |
| 312 | f.input.ensureTotalCapacity(old_input.len + 1) catch @panic("mmap file resize failed"); | 315 | f.input.ensureTotalCapacity(old_input.len + 1) catch @panic("mmap file resize failed"); |
| 313 | switch (mutation) { | 316 | sw: switch (mutation) { |
| 314 | .remove_byte => { | 317 | .remove_byte => { |
| | 318 | if (old_input.len == 0) continue :sw .add_byte; |
| 315 | const omitted_index = rng.uintLessThanBiased(usize, old_input.len); | 319 | const omitted_index = rng.uintLessThanBiased(usize, old_input.len); |
| 316 | f.input.appendSliceAssumeCapacity(old_input[0..omitted_index]); | 320 | f.input.appendSliceAssumeCapacity(old_input[0..omitted_index]); |
| 317 | f.input.appendSliceAssumeCapacity(old_input[omitted_index + 1 ..]); | 321 | f.input.appendSliceAssumeCapacity(old_input[omitted_index + 1 ..]); |
| 318 | }, | 322 | }, |
| 319 | .modify_byte => { | 323 | .modify_byte => { |
| | 324 | if (old_input.len == 0) continue :sw .add_byte; |
| 320 | const modified_index = rng.uintLessThanBiased(usize, old_input.len); | 325 | const modified_index = rng.uintLessThanBiased(usize, old_input.len); |
| 321 | f.input.appendSliceAssumeCapacity(old_input); | 326 | f.input.appendSliceAssumeCapacity(old_input); |
| 322 | f.input.items[modified_index] = rng.int(u8); | 327 | f.input.items[modified_index] = rng.int(u8); |
| 323 | }, | 328 | }, |
| 324 | .add_byte => { | 329 | .add_byte => { |
| 325 | const modified_index = rng.uintLessThanBiased(usize, old_input.len); | 330 | const modified_index = if (old_input.len == 0) 0 else rng.uintLessThanBiased(usize, old_input.len); |
| 326 | f.input.appendSliceAssumeCapacity(old_input[0..modified_index]); | 331 | f.input.appendSliceAssumeCapacity(old_input[0..modified_index]); |
| 327 | f.input.appendAssumeCapacity(rng.int(u8)); | 332 | f.input.appendAssumeCapacity(rng.int(u8)); |
| 328 | f.input.appendSliceAssumeCapacity(old_input[modified_index..]); | 333 | f.input.appendSliceAssumeCapacity(old_input[modified_index..]); |
| ... | @@ -468,27 +473,55 @@ export fn fuzzer_init(cache_dir_struct: Fuzzer.Slice) void { | ... | @@ -468,27 +473,55 @@ export fn fuzzer_init(cache_dir_struct: Fuzzer.Slice) void { |
| 468 | // Linkers are expected to automatically add `__start_<section>` and | 473 | // Linkers are expected to automatically add `__start_<section>` and |
| 469 | // `__stop_<section>` symbols when section names are valid C identifiers. | 474 | // `__stop_<section>` symbols when section names are valid C identifiers. |
| 470 | | 475 | |
| 471 | const pc_counters_start = @extern([*]u8, .{ | 476 | const pc_counters_start = switch (builtin.os.tag) { |
| 472 | .name = "__start___sancov_cntrs", | 477 | .linux => @extern([*]u8, .{ |
| 473 | .linkage = .weak, | 478 | .name = "__start___sancov_cntrs", |
| 474 | }) orelse fatal("missing __start___sancov_cntrs symbol", .{}); | 479 | .linkage = .weak, |
| | 480 | }) orelse fatal("missing __start___sancov_cntrs symbol", .{}), |
| | 481 | .macos => @extern([*]u8, .{ |
| | 482 | .name = "\x01section$start$__DATA$__sancov_cntrs", |
| | 483 | .linkage = .weak, |
| | 484 | }) orelse fatal("missing section$start$__DATA$__sancov_cntrs symbol", .{}), |
| | 485 | else => @compileError("TODO: implement fuzzing support for the target platform"), |
| | 486 | }; |
| 475 | | 487 | |
| 476 | const pc_counters_end = @extern([*]u8, .{ | 488 | const pc_counters_end = switch (builtin.os.tag) { |
| 477 | .name = "__stop___sancov_cntrs", | 489 | .linux => @extern([*]u8, .{ |
| 478 | .linkage = .weak, | 490 | .name = "__stop___sancov_cntrs", |
| 479 | }) orelse fatal("missing __stop___sancov_cntrs symbol", .{}); | 491 | .linkage = .weak, |
| | 492 | }) orelse fatal("missing __stop___sancov_cntrs symbol", .{}), |
| | 493 | .macos => @extern([*]u8, .{ |
| | 494 | .name = "\x01section$end$__DATA$__sancov_cntrs", |
| | 495 | .linkage = .weak, |
| | 496 | }) orelse fatal("missing section$end$__DATA$__sancov_cntrs symbol", .{}), |
| | 497 | else => @compileError("TODO: implement fuzzing support for the target platform"), |
| | 498 | }; |
| 480 | | 499 | |
| 481 | const pc_counters = pc_counters_start[0 .. pc_counters_end - pc_counters_start]; | 500 | const pc_counters = pc_counters_start[0 .. pc_counters_end - pc_counters_start]; |
| 482 | | 501 | |
| 483 | const pcs_start = @extern([*]usize, .{ | 502 | const pcs_start = switch (builtin.os.tag) { |
| 484 | .name = "__start___sancov_pcs1", | 503 | .linux => @extern([*]usize, .{ |
| 485 | .linkage = .weak, | 504 | .name = "__start___sancov_pcs1", |
| 486 | }) orelse fatal("missing __start___sancov_pcs1 symbol", .{}); | 505 | .linkage = .weak, |
| | 506 | }) orelse fatal("missing __start___sancov_pcs1 symbol", .{}), |
| | 507 | .macos => @extern([*]usize, .{ |
| | 508 | .name = "\x01section$start$__DATA_CONST$__sancov_pcs1", |
| | 509 | .linkage = .weak, |
| | 510 | }) orelse fatal("missing section$start$__DATA_CONST$__sancov_pcs1 symbol", .{}), |
| | 511 | else => @compileError("TODO: implement fuzzing support for the target platform"), |
| | 512 | }; |
| 487 | | 513 | |
| 488 | const pcs_end = @extern([*]usize, .{ | 514 | const pcs_end = switch (builtin.os.tag) { |
| 489 | .name = "__stop___sancov_pcs1", | 515 | .linux => @extern([*]usize, .{ |
| 490 | .linkage = .weak, | 516 | .name = "__stop___sancov_pcs1", |
| 491 | }) orelse fatal("missing __stop___sancov_pcs1 symbol", .{}); | 517 | .linkage = .weak, |
| | 518 | }) orelse fatal("missing __stop___sancov_pcs1 symbol", .{}), |
| | 519 | .macos => @extern([*]usize, .{ |
| | 520 | .name = "\x01section$end$__DATA_CONST$__sancov_pcs1", |
| | 521 | .linkage = .weak, |
| | 522 | }) orelse fatal("missing section$end$__DATA_CONST$__sancov_pcs1 symbol", .{}), |
| | 523 | else => @compileError("TODO: implement fuzzing support for the target platform"), |
| | 524 | }; |
| 492 | | 525 | |
| 493 | const pcs = pcs_start[0 .. pcs_end - pcs_start]; | 526 | const pcs = pcs_start[0 .. pcs_end - pcs_start]; |
| 494 | | 527 | |