@@ -6,6 +6,8 @@ const MemoryMappedList = @import("memory_mapped_list.zig").MemoryMappedList;
6
6
const feature_capture = @import ("feature_capture.zig" );
7
7
8
8
const Allocator = std .mem .Allocator ;
9
+ const File = std .fs .File ;
10
+ const Dir = std .fs .Dir ;
9
11
const ArrayList = std .ArrayList ;
10
12
const ArrayListUnmanaged = std .ArrayListUnmanaged ;
11
13
const Options = std .testing .FuzzInputOptions ;
@@ -20,17 +22,6 @@ const InitialFeatureBufferCap = 64;
20
22
// currently unused
21
23
export threadlocal var __sancov_lowest_stack : usize = std .math .maxInt (usize );
22
24
23
- fn createFileBail (dir : std.fs.Dir , sub_path : []const u8 , flags : std.fs.File.CreateFlags ) std.fs.File {
24
- return dir .createFile (sub_path , flags ) catch | err | switch (err ) {
25
- error .FileNotFound = > {
26
- const dir_name = std .fs .path .dirname (sub_path ).? ;
27
- dir .makePath (dir_name ) catch | e | fatal ("makePath '{s}' failed: {}" , .{ dir_name , e });
28
- return dir .createFile (sub_path , flags ) catch | e | fatal ("createFile '{s}' failed: {}" , .{ sub_path , e });
29
- },
30
- else = > | e | fatal ("create file '{s}' failed: {}" , .{ sub_path , e }),
31
- };
32
- }
33
-
34
25
/// Deduplicates array of sorted features
35
26
fn uniq (a : []u32 ) []u32 {
36
27
var write : usize = 0 ;
@@ -138,15 +129,8 @@ fn hashPCs(pcs: []const usize) u64 {
138
129
return hasher .final ();
139
130
}
140
131
141
- /// File contains SeenPcsHeader and trailing data:
142
- /// - list of PC addresses (usize elements)
143
- /// - list of hit flag, 1 bit per address (stored in u8 elements)
144
- fn initCoverageFile (cache_dir : std.fs.Dir , coverage_file_path : []const u8 , pcs : []const usize ) MemoryMappedList (u8 ) {
145
- const coverage_file = createFileBail (cache_dir , coverage_file_path , .{
146
- .read = true ,
147
- .truncate = false ,
148
- });
149
- defer coverage_file .close ();
132
+ /// File contains SeenPcsHeader and its trailing data
133
+ fn initCoverageFile (coverage_file : File , pcs : []const usize ) MemoryMappedList (u8 ) {
150
134
const n_bitset_elems = (pcs .len + @bitSizeOf (usize ) - 1 ) / @bitSizeOf (usize );
151
135
152
136
comptime assert (SeenPcsHeader .trailing [0 ] == .pc_bits_usize );
@@ -161,7 +145,7 @@ fn initCoverageFile(cache_dir: std.fs.Dir, coverage_file_path: []const u8, pcs:
161
145
const existing_len = seen_pcs .items .len ;
162
146
163
147
if (existing_len != 0 and existing_len != bytes_len ) {
164
- fatal ("coverage file '{s}' is invalid (wrong length)" , .{coverage_file_path });
148
+ fatal ("coverage file is invalid (wrong length, wanted {}, is {} )" , .{ bytes_len , existing_len });
165
149
}
166
150
167
151
if (existing_len != 0 ) {
@@ -170,7 +154,7 @@ fn initCoverageFile(cache_dir: std.fs.Dir, coverage_file_path: []const u8, pcs:
170
154
const existing_pcs = std .mem .bytesAsSlice (usize , existing_pcs_bytes );
171
155
for (existing_pcs , pcs ) | old , new | {
172
156
if (old != new ) {
173
- fatal ("coverage file '{s}' is invalid (pc missmatch)" , .{coverage_file_path });
157
+ fatal ("coverage file is invalid (pc missmatch)" , .{});
174
158
}
175
159
}
176
160
} else {
@@ -359,6 +343,46 @@ fn mergeInput(
359
343
updateGlobalCoverage (pc_counters , seen_pcs );
360
344
}
361
345
346
+ const Files = struct { buffer : File , meta : File , coverage : File };
347
+
348
+ fn setupFilesBail (c : Dir , i : u64 ) Files {
349
+ return setupFiles (c , i ) catch | e | fatal ("Failed to setup files: {}" , .{e });
350
+ }
351
+
352
+ fn cleanupFiles (f : Files ) void {
353
+ f .buffer .close ();
354
+ f .meta .close ();
355
+ f .coverage .close ();
356
+ }
357
+
358
+ fn setupFiles (cache_dir : Dir , coverage_id : u64 ) ! Files {
359
+ // we create 1 folder and 3 files:
360
+ // cache/v/
361
+ // cache/v/***buffer
362
+ // cache/v/***meta
363
+ // cache/v/***coverage
364
+
365
+ const hex_digest = std .fmt .hex (coverage_id );
366
+
367
+ const flags = File.CreateFlags { .read = true , .truncate = false };
368
+
369
+ try cache_dir .makeDir ("v" );
370
+
371
+ const v = try cache_dir .openDir ("v" , .{});
372
+ defer v .close ();
373
+
374
+ const buffer = try v .createFile (hex_digest ++ "buffer" , flags );
375
+ errdefer buffer .close ();
376
+
377
+ const meta = try v .createFile (hex_digest ++ "meta" , flags );
378
+ errdefer meta .close ();
379
+
380
+ const coverage = try v .createFile (hex_digest ++ "coverage" , flags );
381
+ errdefer coverage .close ();
382
+
383
+ return .{ .buffer = buffer , .meta = meta , .coverage = coverage };
384
+ }
385
+
362
386
pub const Fuzzer = struct {
363
387
// given to us by LLVM
364
388
pcs : []const usize ,
@@ -368,9 +392,9 @@ pub const Fuzzer = struct {
368
392
/// information, available to other processes.
369
393
coverage_id : u64 ,
370
394
371
- cache_dir : std.fs. Dir ,
395
+ cache_dir : Dir ,
372
396
373
- pub fn init (cache_dir : std.fs. Dir , pc_counters : []u8 , pcs : []usize ) Fuzzer {
397
+ pub fn init (cache_dir : Dir , pc_counters : []u8 , pcs : []usize ) Fuzzer {
374
398
assert (pc_counters .len == pcs .len );
375
399
376
400
return .{
@@ -400,26 +424,23 @@ pub const Fuzzer = struct {
400
424
var feature_buffer = try ArrayListUnmanaged (u32 ).initCapacity (a , InitialFeatureBufferCap );
401
425
defer feature_buffer .deinit (a );
402
426
403
- // Choose a file name for the coverage based on a hash of the PCs that
404
- // will be stored within.
405
- const hex_digest = std .fmt .hex (f .coverage_id );
406
- const coverage_file_path = "v/" ++ hex_digest ++ "coverage" ;
427
+ const files = setupFilesBail (f .cache_dir , f .coverage_id );
428
+ defer cleanupFiles (files );
407
429
408
430
var ip = InputPool .init (f .cache_dir , f .coverage_id );
409
431
defer ip .deinit ();
410
432
411
433
// Tracks which PCs have been seen across all runs that do not crash the fuzzer process.
412
434
// Stored in a memory-mapped file so that it can be shared with other
413
435
// processes and viewed while the fuzzer is running.
414
- const seen_pcs = initCoverageFile (f .cache_dir , coverage_file_path , f .pcs );
415
-
416
- std .log .info ("Coverage id is {s}" , .{& hex_digest });
436
+ const seen_pcs = initCoverageFile (files .coverage , f .pcs );
417
437
418
438
std .log .info (
419
439
\\Initial corpus of size {}
420
440
\\F - this input features
421
441
\\T - new unique features
422
442
, .{ip .len ()});
443
+
423
444
if (ip .len () == 0 ) {
424
445
initialCorpusRandom (& ip , rng );
425
446
}
0 commit comments