authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2024-05-30 11:45:45 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2024-05-30 11:45:45 -07:00
log1b02be0b352c3607057cad5583d856731a54a7cd
tree1636d86de2c7ac58e4c8d133227a0d1d1725f0fa
parent701447f6f0a5d569d2f3f82dd251d2d4873d5ed9

add afl++ instrumentation


5 files changed, 161 insertions(+), 0 deletions(-)

.gitignore+1
...@@ -2,3 +2,4 @@...@@ -2,3 +2,4 @@
2deps.zig2deps.zig
3zig-*3zig-*
4zigmod.lock4zigmod.lock
5fuzz/output
build.zig+48
...@@ -18,4 +18,52 @@ pub fn build(b: *std.Build) void {...@@ -18,4 +18,52 @@ pub fn build(b: *std.Build) void {
1818
19 const test_step = b.step("test", "Run the tests");19 const test_step = b.step("test", "Run the tests");
20 test_step.dependOn(&test_cmd.step);20 test_step.dependOn(&test_cmd.step);
21
22 //
23
24 const fuzz_exe = addFuzzer(b, target, "json", &.{});
25
26 const fuzz_run = b.addSystemCommand(&.{"afl-fuzz"});
27 fuzz_run.step.dependOn(&fuzz_exe.step);
28 fuzz_run.addArgs(&.{ "-i", "fuzz/input" });
29 fuzz_run.addArgs(&.{ "-o", "fuzz/output" });
30 fuzz_run.addArgs(&.{ "-x", "fuzz/json.dict" });
31 fuzz_run.addArg("--");
32 fuzz_run.addFileArg(fuzz_exe.source);
33
34 const fuzz_step = b.step("fuzz", "Run AFL++");
35 fuzz_step.dependOn(&fuzz_run.step);
36}
37
38fn addFuzzer(b: *std.Build, target: std.Build.ResolvedTarget, comptime name: []const u8, afl_clang_args: []const []const u8) *std.Build.Step.InstallFile {
39 // The library
40 const fuzz_lib = b.addStaticLibrary(.{
41 .name = "fuzz-" ++ name,
42 .root_source_file = b.path("fuzz/main.zig"),
43 .target = target,
44 .optimize = .Debug,
45 });
46 fuzz_lib.want_lto = true;
47 fuzz_lib.bundle_compiler_rt = true;
48 // Seems to be necessary for LLVM >= 15
49 fuzz_lib.root_module.pic = true;
50
51 deps.addAllTo(fuzz_lib);
52
53 // Setup the output name
54 const fuzz_executable_name = "fuzz-" ++ name;
55 const fuzz_exe_path = std.fs.path.join(b.allocator, &.{ b.cache_root.path.?, fuzz_executable_name }) catch @panic("OOM");
56
57 // We want `afl-clang-lto -o path/to/output path/to/library`
58 const fuzz_compile = b.addSystemCommand(&.{ "afl-clang-lto", "-v", "-o", fuzz_exe_path });
59 // Add the path to the library file to afl-clang-lto's args
60 fuzz_compile.addArtifactArg(fuzz_lib);
61 // Custom args
62 fuzz_compile.addArgs(afl_clang_args);
63
64 // Install the cached output to the install 'bin' path
65 const fuzz_install = b.addInstallBinFile(.{ .path = fuzz_exe_path }, fuzz_executable_name);
66 fuzz_install.step.dependOn(&fuzz_compile.step);
67
68 return fuzz_install;
21}69}
fuzz/input/input.json created+26
...@@ -0,0 +1,26 @@
1{
2 "Image": {
3 "Width": 800,
4 "Height": 600,
5 "Title": "View from 15th Floor",
6 "Thumbnail": {
7 "Url": "http://www.example.com/image/481989943",
8 "Height": 125,
9 "Width": 100
10 },
11 "Animated": false,
12 "IDs": [
13 116,
14 943,
15 234,
16 38793
17 ],
18 "ArrayOfObject": [
19 {
20 "n": "m"
21 }
22 ],
23 "double": 1.3412,
24 "LargeInt": 18446744073709551615
25 }
26}
fuzz/json.dict created+61
...@@ -0,0 +1,61 @@
1#
2# AFL dictionary for JSON
3# -----------------------
4#
5# Just the very basics.
6#
7# Inspired by a dictionary by Jakub Wilk <jwilk@jwilk.net>
8#
9
10"0"
11",0"
12":0"
13"0:"
14"-1.2e+3"
15
16"true"
17"false"
18"null"
19
20"\"\""
21",\"\""
22":\"\""
23"\"\":"
24
25"{}"
26",{}"
27":{}"
28"{\"\":0}"
29"{{}}"
30
31"[]"
32",[]"
33":[]"
34"[0]"
35"[[]]"
36
37"''"
38"\\"
39"\\b"
40"\\f"
41"\\n"
42"\\r"
43"\\t"
44"\\u0000"
45"\\x00"
46"\\0"
47"\\uD800\\uDC00"
48"\\uDBFF\\uDFFF"
49
50"\"\":0"
51"//"
52"/**/"
53
54"$ref"
55"type"
56"coordinates"
57"@context"
58"@id"
59
60","
61":"
fuzz/main.zig created+25
...@@ -0,0 +1,25 @@
1const std = @import("std");
2const json = @import("json");
3
4comptime {
5 @export(cMain, .{ .name = "main", .linkage = .strong });
6}
7
8fn cMain() callconv(.C) void {
9 main();
10}
11
12pub fn main() void {
13 // Setup an allocator that will detect leaks/use-after-free/etc
14 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
15 // this will check for leaks and crash the program if it finds any
16 defer std.debug.assert(gpa.deinit() == .ok);
17 const allocator = gpa.allocator();
18
19 // Read the data from stdin
20 const stdin = std.io.getStdIn();
21
22 // Try to parse the data
23 var parsed = json.parse(allocator, "[stdin]", stdin.reader()) catch return;
24 defer parsed.deinit(allocator);
25}