From 795da1817bce9d07a99d2a8be65291fe8507f592 Mon Sep 17 00:00:00 2001 From: jwstolk Date: Fri, 15 Aug 2025 22:44:21 +0200 Subject: [PATCH] fuzz: prevent pcs slice panic and null-base memcpy; ensure capacity before first append - std/Build.Fuzz.addEntryPoint: guard pcs.len==0 and make logs bounds-safe. - lib/fuzzer.zig: - appendSliceAssumeCapacity: early-return on zero-length; copy to [old_len .. old_len+len]. - start(): ensureTotalCapacity before first append when corpus is empty (TODO: revisit invariant). --- lib/fuzzer.zig | 2 ++ lib/std/Build/Fuzz.zig | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/lib/fuzzer.zig b/lib/fuzzer.zig index 7f1592f0de7c..bdeb4f805eda 100644 --- a/lib/fuzzer.zig +++ b/lib/fuzzer.zig @@ -279,6 +279,7 @@ const Fuzzer = struct { const len = rng.uintLessThanBiased(usize, 200); const slice = try gpa.alloc(u8, len); rng.bytes(slice); + f.input.ensureTotalCapacity(len) catch @panic("mmap file resize failed"); // TODO: Not clear yet what causes the capacity assumption to be false. f.input.appendSliceAssumeCapacity(slice); try f.corpus.append(gpa, .{ .bytes = slice, @@ -600,6 +601,7 @@ pub const MemoryMappedList = struct { /// Append the slice of items to the list. /// Asserts that the list can hold the additional items. pub fn appendSliceAssumeCapacity(l: *MemoryMappedList, items: []const u8) void { + if (items.len == 0) return; const old_len = l.items.len; const new_len = old_len + items.len; assert(new_len <= l.capacity); diff --git a/lib/std/Build/Fuzz.zig b/lib/std/Build/Fuzz.zig index bc10f7907a2e..ff8978042ce4 100644 --- a/lib/std/Build/Fuzz.zig +++ b/lib/std/Build/Fuzz.zig @@ -422,6 +422,10 @@ fn addEntryPoint(fuzz: *Fuzz, coverage_id: u64, addr: u64) error{ AlreadyReporte const coverage_map = fuzz.coverage_files.getPtr(coverage_id).?; const header: *const abi.SeenPcsHeader = @ptrCast(coverage_map.mapped_memory[0..@sizeOf(abi.SeenPcsHeader)]); const pcs = header.pcAddrs(); + if (pcs.len == 0) { + log.err("no program counters recorded for unit test (coverage_id=0x{x}); addr=0x{x}", .{ coverage_id, addr }); + return error.AlreadyReported; + } // Since this pcs list is unsorted, we must linear scan for the best index. const index = i: {