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.
pull/12398/head
Mitchell Hashimoto 2026-04-23 08:40:40 -07:00
parent b34c62bf04
commit ae1dd5666d
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
3 changed files with 25 additions and 1 deletions

View File

@ -227,8 +227,22 @@ in
unset SDKROOT unset SDKROOT
unset DEVELOPER_DIR unset DEVELOPER_DIR
# AFL++ needs to use the Homebrew/system Apple toolchain directly.
# The Nix compiler wrapper variables leak a Nix linker into afl-cc,
# which breaks even trivial fuzz harness links on macOS.
unset NIX_CC
unset NIX_CFLAGS_COMPILE
unset NIX_LDFLAGS
unset LD
unset CC
unset CXX
unset CFLAGS
unset CPPFLAGS
unset LDFLAGS
# We need to remove "xcrun" from the PATH. It is injected by # We need to remove "xcrun" from the PATH. It is injected by
# some dependency but we need to rely on system Xcode tools # some dependency but we need to rely on system Xcode tools
export PATH=$(echo "$PATH" | awk -v RS=: -v ORS=: '$0 !~ /xcrun/ || $0 == "/usr/bin" {print}' | sed 's/:$//') export PATH=$(echo "$PATH" | awk -v RS=: -v ORS=: '$0 !~ /xcrun/ || $0 == "/usr/bin" {print}' | sed 's/:$//')
export PATH="/opt/homebrew/opt/llvm/bin:/opt/homebrew/bin:/usr/local/opt/llvm/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH"
''); '');
} }

View File

@ -1,4 +1,5 @@
const std = @import("std"); const std = @import("std");
const builtin = @import("builtin");
/// Creates a build step that produces an AFL++-instrumented fuzzing /// Creates a build step that produces an AFL++-instrumented fuzzing
/// executable. /// executable.
@ -23,6 +24,12 @@ pub fn addInstrumentedExe(
@panic("Could not find 'afl-cc', which is required to build"), @panic("Could not find 'afl-cc', which is required to build"),
"-O3", "-O3",
}); });
if (builtin.target.os.tag.isDarwin()) {
// Apple's newer ld asserts on the custom section names emitted by
// AFL's LLVM instrumentation when linking our Zig-produced bitcode.
// lld links the same inputs without issue.
afl_cc.addArg("-fuse-ld=lld");
}
afl_cc.addArg("-o"); afl_cc.addArg("-o");
const fuzz_exe = afl_cc.addOutputFileArg(obj.name); const fuzz_exe = afl_cc.addOutputFileArg(obj.name);
afl_cc.addFileArg(pkg.path("afl.c")); afl_cc.addFileArg(pkg.path("afl.c"));

View File

@ -23,7 +23,10 @@ const fuzzers: []const Fuzzer = &.{
}; };
pub fn build(b: *std.Build) void { pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{}); // 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 optimize = b.standardOptimizeOption(.{});
const ghostty_dep = b.lazyDependency("ghostty", .{ const ghostty_dep = b.lazyDependency("ghostty", .{