| ... | ... | @@ -17,12 +17,7 @@ fn logOverride( |
| 17 | 17 | comptime format: []const u8, |
| 18 | 18 | args: anytype, |
| 19 | 19 | ) void { |
| 20 | | const f = if (log_file) |f| f else f: { |
| 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 | | }; |
| 20 | const f = if (log_file) |f| f else return; |
| 26 | 21 | const prefix1 = comptime level.asText(); |
| 27 | 22 | const prefix2 = if (scope == .default) ": " else "(" ++ @tagName(scope) ++ "): "; |
| 28 | 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 | 93 | |
| 99 | 94 | fn handleCmp(pc: usize, arg1: u64, arg2: u64) void { |
| 100 | 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 | 99 | const Fuzzer = struct { |
| 100 | inited: bool = false, |
| 105 | 101 | rng: std.Random.DefaultPrng, |
| 106 | 102 | pcs: []const usize, |
| 107 | 103 | pc_counters: []u8, |
| ... | ... | @@ -157,6 +153,9 @@ const Fuzzer = struct { |
| 157 | 153 | f.pc_counters = pc_counters; |
| 158 | 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 | 159 | // Choose a file name for the coverage based on a hash of the PCs that will be stored within. |
| 161 | 160 | const pc_digest = std.hash.Wyhash.hash(0, std.mem.sliceAsBytes(pcs)); |
| 162 | 161 | f.coverage_id = pc_digest; |
| ... | ... | @@ -210,6 +209,8 @@ const Fuzzer = struct { |
| 210 | 209 | f.seen_pcs.appendNTimesAssumeCapacity(0, n_bitset_elems * @sizeOf(usize)); |
| 211 | 210 | f.seen_pcs.appendSliceAssumeCapacity(std.mem.sliceAsBytes(pcs)); |
| 212 | 211 | } |
| 212 | |
| 213 | f.inited = true; |
| 213 | 214 | } |
| 214 | 215 | |
| 215 | 216 | fn initNextInput(f: *Fuzzer) void { |
| ... | ... | @@ -296,7 +297,9 @@ const Fuzzer = struct { |
| 296 | 297 | /// where it branches. |
| 297 | 298 | fn traceValue(f: *Fuzzer, x: usize) void { |
| 298 | 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 | 305 | const Mutation = enum { |
| ... | ... | @@ -310,19 +313,21 @@ const Fuzzer = struct { |
| 310 | 313 | f.input.clearRetainingCapacity(); |
| 311 | 314 | const old_input = f.corpus.items[corpus_index].bytes; |
| 312 | 315 | f.input.ensureTotalCapacity(old_input.len + 1) catch @panic("mmap file resize failed"); |
| 313 | | switch (mutation) { |
| 316 | sw: switch (mutation) { |
| 314 | 317 | .remove_byte => { |
| 318 | if (old_input.len == 0) continue :sw .add_byte; |
| 315 | 319 | const omitted_index = rng.uintLessThanBiased(usize, old_input.len); |
| 316 | 320 | f.input.appendSliceAssumeCapacity(old_input[0..omitted_index]); |
| 317 | 321 | f.input.appendSliceAssumeCapacity(old_input[omitted_index + 1 ..]); |
| 318 | 322 | }, |
| 319 | 323 | .modify_byte => { |
| 324 | if (old_input.len == 0) continue :sw .add_byte; |
| 320 | 325 | const modified_index = rng.uintLessThanBiased(usize, old_input.len); |
| 321 | 326 | f.input.appendSliceAssumeCapacity(old_input); |
| 322 | 327 | f.input.items[modified_index] = rng.int(u8); |
| 323 | 328 | }, |
| 324 | 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 | 331 | f.input.appendSliceAssumeCapacity(old_input[0..modified_index]); |
| 327 | 332 | f.input.appendAssumeCapacity(rng.int(u8)); |
| 328 | 333 | f.input.appendSliceAssumeCapacity(old_input[modified_index..]); |
| ... | ... | @@ -468,27 +473,55 @@ export fn fuzzer_init(cache_dir_struct: Fuzzer.Slice) void { |
| 468 | 473 | // Linkers are expected to automatically add `__start_<section>` and |
| 469 | 474 | // `__stop_<section>` symbols when section names are valid C identifiers. |
| 470 | 475 | |
| 471 | | const pc_counters_start = @extern([*]u8, .{ |
| 472 | | .name = "__start___sancov_cntrs", |
| 473 | | .linkage = .weak, |
| 474 | | }) orelse fatal("missing __start___sancov_cntrs symbol", .{}); |
| 476 | const pc_counters_start = switch (builtin.os.tag) { |
| 477 | .linux => @extern([*]u8, .{ |
| 478 | .name = "__start___sancov_cntrs", |
| 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, .{ |
| 477 | | .name = "__stop___sancov_cntrs", |
| 478 | | .linkage = .weak, |
| 479 | | }) orelse fatal("missing __stop___sancov_cntrs symbol", .{}); |
| 488 | const pc_counters_end = switch (builtin.os.tag) { |
| 489 | .linux => @extern([*]u8, .{ |
| 490 | .name = "__stop___sancov_cntrs", |
| 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 | 500 | const pc_counters = pc_counters_start[0 .. pc_counters_end - pc_counters_start]; |
| 482 | 501 | |
| 483 | | const pcs_start = @extern([*]usize, .{ |
| 484 | | .name = "__start___sancov_pcs1", |
| 485 | | .linkage = .weak, |
| 486 | | }) orelse fatal("missing __start___sancov_pcs1 symbol", .{}); |
| 502 | const pcs_start = switch (builtin.os.tag) { |
| 503 | .linux => @extern([*]usize, .{ |
| 504 | .name = "__start___sancov_pcs1", |
| 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, .{ |
| 489 | | .name = "__stop___sancov_pcs1", |
| 490 | | .linkage = .weak, |
| 491 | | }) orelse fatal("missing __stop___sancov_pcs1 symbol", .{}); |
| 514 | const pcs_end = switch (builtin.os.tag) { |
| 515 | .linux => @extern([*]usize, .{ |
| 516 | .name = "__stop___sancov_pcs1", |
| 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 | 526 | const pcs = pcs_start[0 .. pcs_end - pcs_start]; |
| 494 | 527 | |