authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2025-08-25 02:05:22 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2025-08-25 02:05:22 -07:00
log4aa6a3f8344a450433a21862890e791c76bb464b
tree294c1b758e84c27e61d3e7c602cf6cdfba154291
parentb0fb5f64914ea219b35b778c371fa4d8237b8526

add fuzzing


6 files changed, 181 insertions(+), 0 deletions(-)

.gitignore+2
......@@ -2,3 +2,5 @@
22.zigmod
33zigmod.lock
44deps.zig
5zig-out
6fuzz/output
build.zig+43
......@@ -23,4 +23,47 @@ pub fn build(b: *std.Build) void {
2323 const tests_run = b.addRunArtifact(tests);
2424 tests_run.has_side_effects = true;
2525 test_step.dependOn(&tests_run.step);
26
27 //
28
29 const fuzz_exe = addFuzzer(b, target, "yaml", &.{});
30
31 const fuzz_run = b.addSystemCommand(&.{"afl-fuzz"});
32 fuzz_run.step.dependOn(&fuzz_exe.step);
33 fuzz_run.addArgs(&.{ "-i", "fuzz/input" });
34 fuzz_run.addArgs(&.{ "-o", "fuzz/output" });
35 fuzz_run.addArgs(&.{ "-x", "fuzz/yaml.dict" });
36 fuzz_run.addArg("--");
37 fuzz_run.addFileArg(fuzz_exe.source);
38
39 const fuzz_step = b.step("fuzz", "Run AFL++");
40 fuzz_step.dependOn(&fuzz_run.step);
41}
42
43fn addFuzzer(b: *std.Build, target: std.Build.ResolvedTarget, comptime name: []const u8, afl_clang_args: []const []const u8) *std.Build.Step.InstallFile {
44 const fuzz_lib = b.addStaticLibrary(.{
45 .name = "fuzz-" ++ name ++ "-lib",
46 .root_source_file = b.path("fuzz/main.zig"),
47 .target = target,
48 .optimize = .Debug,
49 });
50 fuzz_lib.want_lto = true;
51 fuzz_lib.bundle_compiler_rt = true;
52 fuzz_lib.use_llvm = true;
53 fuzz_lib.use_lld = true;
54 fuzz_lib.root_module.pic = true;
55
56 deps.addAllTo(fuzz_lib);
57
58 const fuzz_executable_name = "fuzz-" ++ name;
59
60 const fuzz_compile = b.addSystemCommand(&.{ "afl-clang-lto", "-v", "-o" });
61 const output_path = fuzz_compile.addOutputFileArg(fuzz_executable_name);
62 fuzz_compile.addArtifactArg(fuzz_lib);
63 fuzz_compile.addArgs(afl_clang_args);
64
65 const fuzz_install = b.addInstallBinFile(output_path, fuzz_executable_name);
66 fuzz_install.step.dependOn(&fuzz_compile.step);
67
68 return fuzz_install;
2669}
fuzz/input/input.yml created+31
......@@ -0,0 +1,31 @@
1id: g982zq6e8wsvnmduerpbf8787hu85brugmngn8wf
2name: yaml
3main: yaml.zig
4license: MIT
5description: A Yaml parser built on top of libyaml
6dependencies:
7 - src: git https://github.com/yaml/libyaml tag-0.2.5
8 id: 8mdbh0zuneb0i3hs5jby5je0heem1i6yxusl7c8y8qx68hqc
9 license: MIT
10 c_include_dirs:
11 - include
12 c_source_flags:
13 - -DYAML_VERSION_MAJOR=0
14 - -DYAML_VERSION_MINOR=2
15 - -DYAML_VERSION_PATCH=5
16 - -DYAML_VERSION_STRING="0.2.5"
17 - -DYAML_DECLARE_STATIC=1
18 c_source_files:
19 - src/api.c
20 - src/dumper.c
21 - src/emitter.c
22 - src/loader.c
23 - src/parser.c
24 - src/reader.c
25 - src/scanner.c
26 - src/writer.c
27
28 - src: git https://github.com/nektro/zig-extras
29
30root_dependencies:
31 - src: git https://github.com/nektro/zig-expect
fuzz/main.zig created+16
......@@ -0,0 +1,16 @@
1const std = @import("std");
2const yaml = @import("yaml");
3const nfs = @import("nfs");
4
5pub export fn main() void {
6 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
7 defer std.debug.assert(gpa.deinit() == .ok);
8 const allocator = gpa.allocator();
9
10 const stdin = nfs.stdin();
11 const input = stdin.readToEndAlloc(allocator, 1024 * 1024, null) catch @panic("too big");
12 defer allocator.free(input);
13
14 const doc = yaml.parse(allocator, input) catch return;
15 defer doc.deinit(allocator);
16}
fuzz/yaml.dict created+80
......@@ -0,0 +1,80 @@
1# https://github.com/AFLplusplus/AFLplusplus/blob/stable/dictionaries/yaml.dict
2# sources:
3# - https://en.wikipedia.org/wiki/YAML
4# - https://yaml.org/spec/1.1/
5# - https://yaml.org/type/
6
7directive_yaml="%YAML 1.2"
8directive_tag="%TAG !yaml! tag:yaml.org,2002:"
9directive_tag2="%TAG !m! !my-"
10true="true"
11caps_true="TRUE"
12caps_false="FALSE"
13literal_true="YES"
14literal_false="NO"
15false="false"
16start="---"
17comment="#"
18list="- "
19key="k: "
20walrus="=:"
21question_key="?k: "
22number="\"0e5\""
23expand="!!"
24list="[a,b]"
25dict="{k: v, x: y}"
26value=": v"
27exponent="e+03"
28neg_inf="-.inf"
29nan=".NaN"
30end="..."
31quoted_key="'k'"
32newline="k: |"
33newline2="k: >"
34anchor="&a"
35reference="*a"
36type_binary="!!binary"
37type_bool="!!bool"
38type_float="!!float"
39type_int="!!int"
40type_map="!!map"
41type_merge="!!merge"
42type_null="!!null"
43type_omap="!!omap"
44type_pairs="!!pairs"
45type_seq="!!seq"
46type_set="!!set"
47type_str="!!str"
48type_timestamp="!!timestamp"
49type_value="!!value"
50type_yaml="!!yaml"
51type_python="!!python"
52merge = "<<"
53number_separation="_"
54decimal_number="+30_123"
55octal_number="0123"
56hex_number="0x_12_23"
57bin_number="0b1001_1001"
58sexa_number="123:34:75"
59complex_mapping="? "
60litteral_style=" |"
61folded_style=" >"
62timestamp="2001-12-14t21:59:43.10-05:00"
63escaped_unicode="\\u2029"
64"["
65"]"
66"{"
67"}"
68"-"
69","
70"&"
71"<<"
72":"
73"|"
74"!!"
75">"
76"\""
77"'"
78integer="123"
79float="12.5"
80mantissa="1.3e+9"
shell.nix created+9
......@@ -0,0 +1,9 @@
1with import <nixpkgs> {};
2
3pkgs.mkShell {
4 nativeBuildInputs = with pkgs; [
5 aflplusplus
6 ];
7
8 hardeningDisable = [ "all" ];
9}