Files
ghostty/test/fuzz-libghostty/build.zig
Mitchell Hashimoto ae1dd5666d fuzz: fix macOS AFL toolchain and linker setup for macOS 26.4
On macOS 26.4, AFL builds were picking up Nix compiler-wrapper
variables and Apple SDK target settings from the shell environment.
That caused afl-cc to drive the wrong linker and target configuration,
which broke even simple fuzz harness builds. Unset the Nix compiler and 
linker environment in the fuzz dev shell so AFL++ uses the system or 
Homebrew Apple toolchain directly. 

Also force afl-cc to link with lld because the newer Apple linker
asserts on the custom sections emitted by AFL's LLVM
instrumentation. Finally, pin fuzz-libghostty to the host target so the
build does not inherit stray SDK targets from the environment.
2026-04-23 09:06:12 -07:00

77 lines
2.2 KiB
Zig

const std = @import("std");
const afl = @import("afl");
/// Possible fuzz targets. Each fuzz target is implemented in
/// src/fuzz_<name>.zig and has an initial corpus in corpus/<name>-initial.
const Fuzzer = struct {
name: []const u8,
pub fn source(comptime self: Fuzzer) []const u8 {
return "src/fuzz_" ++ self.name ++ ".zig";
}
pub fn corpus(comptime self: Fuzzer) []const u8 {
// Change this suffix to use cmin vs initial corpus
return "corpus/" ++ self.name ++ "-cmin";
}
};
const fuzzers: []const Fuzzer = &.{
.{ .name = "osc" },
.{ .name = "parser" },
.{ .name = "stream" },
};
pub fn build(b: *std.Build) void {
// Resolve a "generic" host target so the emitted LLVM bitcode does not
// contain native CPU features (e.g. +zcm, +zcz) that the LLVM version
// bundled with afl-cc may not recognise, which would produce warnings.
const target = b.resolveTargetQuery(.{});
const optimize = b.standardOptimizeOption(.{});
const ghostty_dep = b.lazyDependency("ghostty", .{
.simd = false,
});
inline for (fuzzers) |fuzzer| {
const run_step = b.step(
b.fmt("run-{s}", .{fuzzer.name}),
b.fmt("Run {s} with afl-fuzz", .{fuzzer.name}),
);
const lib_mod = b.createModule(.{
.root_source_file = b.path(fuzzer.source()),
.target = target,
.optimize = optimize,
});
if (ghostty_dep) |dep| {
lib_mod.addImport(
"ghostty-vt",
dep.module("ghostty-vt"),
);
}
const lib = b.addLibrary(.{
.name = fuzzer.name,
.root_module = lib_mod,
});
lib.root_module.stack_check = false;
lib.root_module.fuzz = true;
const exe = afl.addInstrumentedExe(b, lib);
const run = afl.addFuzzerRun(
b,
exe,
b.path(fuzzer.corpus()),
b.path(b.fmt("afl-out/{s}", .{fuzzer.name})),
);
run_step.dependOn(&run.step);
const exe_install = b.addInstallBinFile(
exe,
"fuzz-" ++ fuzzer.name,
);
b.getInstallStep().dependOn(&exe_install.step);
}
}