authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-08-07 21:05:26-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-08-08 21:46:36-07:00
log4e32edbff5d34dfc779797d73bb61d32ffa02953
tree6641a92b99f5488d1891bfb7ef52f3104cc52053
parent2cfad202045632945b5007e1d42c2f8a326be44a

fuzzing: comptime assertions to protect the ABI

compile errors are nice

3 files changed, 21 insertions(+), 1 deletions(-)

lib/fuzzer.zig+7
......@@ -214,6 +214,9 @@ const Fuzzer = struct {
214214 });
215215 defer coverage_file.close();
216216 const n_bitset_elems = (flagged_pcs.len + 7) / 8;
217 comptime assert(SeenPcsHeader.trailing[0] == .pc_addr);
218 comptime assert(SeenPcsHeader.trailing[1][0] == .pc_bits);
219 comptime assert(SeenPcsHeader.trailing[1][1] == u8);
217220 const bytes_len = @sizeOf(SeenPcsHeader) + flagged_pcs.len * @sizeOf(usize) + n_bitset_elems;
218221 const existing_len = coverage_file.getEndPos() catch |err| {
219222 fatal("unable to check len of coverage file: {s}", .{@errorName(err)});
......@@ -301,6 +304,10 @@ const Fuzzer = struct {
301304
302305 // Track code coverage from all runs.
303306 {
307 comptime assert(SeenPcsHeader.trailing[0] == .pc_addr);
308 comptime assert(SeenPcsHeader.trailing[1][0] == .pc_bits);
309 comptime assert(SeenPcsHeader.trailing[1][1] == u8);
310
304311 const seen_pcs = f.seen_pcs.items[@sizeOf(SeenPcsHeader) + f.flagged_pcs.len * @sizeOf(usize) ..];
305312 for (seen_pcs, 0..) |*elem, i| {
306313 const byte_i = i * 8;
lib/std/Build/Fuzz/WebServer.zig+6
......@@ -7,6 +7,7 @@ const Step = std.Build.Step;
77const Coverage = std.debug.Coverage;
88const abi = std.Build.Fuzz.abi;
99const log = std.log;
10const assert = std.debug.assert;
1011
1112const WebServer = @This();
1213
......@@ -383,7 +384,10 @@ fn sendCoverageContext(
383384 // TODO: make each events URL correspond to one coverage map
384385 const coverage_map = &coverage_maps[0];
385386 const cov_header: *const abi.SeenPcsHeader = @ptrCast(coverage_map.mapped_memory[0..@sizeOf(abi.SeenPcsHeader)]);
387 comptime assert(abi.SeenPcsHeader.trailing[0] == .pc_addr);
386388 const seen_pcs = coverage_map.mapped_memory[@sizeOf(abi.SeenPcsHeader) + coverage_map.source_locations.len * @sizeOf(usize) ..];
389 comptime assert(abi.SeenPcsHeader.trailing[1][0] == .pc_bits);
390 comptime assert(abi.SeenPcsHeader.trailing[1][1] == u8);
387391 const n_runs = @atomicLoad(usize, &cov_header.n_runs, .monotonic);
388392 const unique_runs = @atomicLoad(usize, &cov_header.unique_runs, .monotonic);
389393 const lowest_stack = @atomicLoad(usize, &cov_header.lowest_stack, .monotonic);
......@@ -630,6 +634,7 @@ fn prepareTables(
630634 gop.value_ptr.mapped_memory = mapped_memory;
631635
632636 const header: *const abi.SeenPcsHeader = @ptrCast(mapped_memory[0..@sizeOf(abi.SeenPcsHeader)]);
637 comptime assert(abi.SeenPcsHeader.trailing[0] == .pc_addr);
633638 const pcs_bytes = mapped_memory[@sizeOf(abi.SeenPcsHeader)..][0 .. header.pcs_len * @sizeOf(usize)];
634639 const pcs = std.mem.bytesAsSlice(usize, pcs_bytes);
635640 const source_locations = try gpa.alloc(Coverage.SourceLocation, pcs.len);
......@@ -649,6 +654,7 @@ fn addEntryPoint(ws: *WebServer, coverage_id: u64, addr: u64) error{ AlreadyRepo
649654
650655 const coverage_map = ws.coverage_files.getPtr(coverage_id).?;
651656 const ptr = coverage_map.mapped_memory;
657 comptime assert(abi.SeenPcsHeader.trailing[0] == .pc_addr);
652658 const pcs_bytes = ptr[@sizeOf(abi.SeenPcsHeader)..][0 .. coverage_map.source_locations.len * @sizeOf(usize)];
653659 const pcs: []const usize = @alignCast(std.mem.bytesAsSlice(usize, pcs_bytes));
654660 const index = std.sort.upperBound(usize, pcs, addr, struct {
lib/std/Build/Fuzz/abi.zig+8-1
......@@ -8,12 +8,19 @@
88///
99/// Trailing:
1010/// * pc_addr: usize for each pcs_len
11/// * 1 bit per pc_addr, usize elements
11/// * 1 bit per pc_addr, u8 elements
1212pub const SeenPcsHeader = extern struct {
1313 n_runs: usize,
1414 unique_runs: usize,
1515 pcs_len: usize,
1616 lowest_stack: usize,
17
18 /// Used for comptime assertions. Provides a mechanism for strategically
19 /// causing compile errors.
20 pub const trailing = .{
21 .pc_addr,
22 .{ .pc_bits, u8 },
23 };
1724};
1825
1926pub const ToClientTag = enum(u8) {