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 };