lib/deadalloc/src/report.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 pub const IssueKind = enum {
 2     invalid_free,
 3     double_free,
 4     buffer_overflow,
 5     use_after_free,
 6     leak,
 7     size_mismatch,
 8 };
 9 
10 pub const Issue = struct {
11     kind: IssueKind = .invalid_free,
12     address: usize = 0,
13     offset: usize = 0,
14     requested_len: usize = 0,
15     block_size: usize = 0,
16     allocation_id: u64 = 0,
17     allocation_return_address: usize = 0,
18     free_return_address: usize = 0,
19     free_epoch: u64 = 0,
20     return_address: usize = 0,
21 };
22 
23 pub const max_issues: usize = 32;
24 
25 pub const IssueLog = struct {
26     count: usize = 0,
27     dropped: usize = 0,
28     items: [max_issues]Issue = @as([max_issues]Issue, @splat(.{})),
29 
30     pub fn append(self: *IssueLog, issue: Issue) void {
31         if (self.count < self.items.len) {
32             self.items[self.count] = issue;
33             self.count += 1;
34             return;
35         }
36         self.dropped += 1;
37     }
38 
39     pub fn slice(self: *const IssueLog) []const Issue {
40         return self.items[0..self.count];
41     }
42 };
43 
44 pub const Counters = struct {
45     invalid_free: usize = 0,
46     double_free: usize = 0,
47     buffer_overflow: usize = 0,
48     use_after_free: usize = 0,
49     size_mismatch: usize = 0,
50 
51     pub fn issueCount(self: Counters) usize {
52         return self.invalid_free +
53             self.double_free +
54             self.buffer_overflow +
55             self.use_after_free +
56             self.size_mismatch;
57     }
58 
59     pub fn increment(self: *Counters, kind: IssueKind) void {
60         switch (kind) {
61             .invalid_free => self.invalid_free += 1,
62             .double_free => self.double_free += 1,
63             .buffer_overflow => self.buffer_overflow += 1,
64             .use_after_free => self.use_after_free += 1,
65             .size_mismatch => self.size_mismatch += 1,
66             .leak => {},
67         }
68     }
69 };
70 
71 pub const Report = struct {
72     counters: Counters = .{},
73     live_allocations: usize = 0,
74     live_bytes: usize = 0,
75     leak_count: usize = 0,
76     leak_issue: ?Issue = null,
77     last_issue: ?Issue = null,
78     issues: IssueLog = .{},
79 
80     pub fn isClean(self: Report) bool {
81         return self.counters.issueCount() == 0 and self.leak_count == 0;
82     }
83 
84     pub fn issueSlice(self: *const Report) []const Issue {
85         return self.issues.slice();
86     }
87 };