lib/deadalloc/src/root.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 //! The heap places each allocation at a block drawn at random from its size
 2 //! class, a *randomized heap*, over an allocator the caller supplies. The heap
 3 //! follows one of three published designs as its *mode*: `diehard`,
 4 //! `dieharder`, or `exterminator`. A caller puts this heap under a program that
 5 //! is corrupting its own memory, either to survive the corruption or to find
 6 //! out where it comes from. The heap stores that `std.mem.Allocator` at init
 7 //! and asks it for the memory it carves up, the *backing allocator*.
 8 //!
 9 //! A request up to 1 MiB takes the first block size at least as large as itself
10 //! from a fixed list of powers of two from 16 bytes upward, the *size class*,
11 //! and a larger request goes to the backing allocator on its own. Each class
12 //! holds more blocks than the live count needs, because the heap grows the
13 //! class once eight times the live count plus one reaches seven times its
14 //! capacity. A request takes a block drawn at random from the whole capacity of
15 //! its class, so which allocation sits next to which is unpredictable from one
16 //! run to the next.
17 //!
18 //! The mode sets a count of allocation epochs a freed block stays unusable, a
19 //! *quarantine epoch*: zero for `diehard`, at least eight for `dieharder`, and
20 //! at least one for `exterminator`, so a write through a freed pointer still
21 //! lands in the block that pointer had.
22 //!
23 //! With diagnostics on, the heap places canary bytes around each block whose
24 //! pattern a later check reads, a *red zone*. When that pattern changed, a
25 //! later check records the memory-safety fault with its kind, its address, its
26 //! offset, its sizes, and the return addresses of the allocation and the free,
27 //! an *issue*. `report` answers with live counts, live bytes, per-kind
28 //! counters, and the bounded array of issues a run keeps, the *issue log*. This
29 //! log holds up to 32 issues and counts the ones past that bound as dropped. An
30 //! issue's kind is one of invalid free, double free, buffer overflow, use after
31 //! free, leak, and size mismatch.
32 //!
33 //! `Config.repaired` reads a report into per-call-site padding and quarantine
34 //! extensions, forming a *repair table*: padding for a call site whose
35 //! allocations overflowed, and longer quarantine for a site whose memory was
36 //! used after the free, returned as a config in `exterminator` mode. A later
37 //! run under that config pads the allocations of the named site and extends the
38 //! quarantine of the named free, so the program can keep running while the bug
39 //! is fixed.
40 
41 const allocator_mod = @import("allocator.zig");
42 const exterminator_mod = @import("exterminator.zig");
43 const report_mod = @import("report.zig");
44 
45 pub const Config = allocator_mod.Config;
46 pub const DeadAllocator = allocator_mod.DeadAllocator;
47 pub const DiagnosticConfig = allocator_mod.DiagnosticConfig;
48 pub const Issue = allocator_mod.Issue;
49 pub const IssueKind = allocator_mod.IssueKind;
50 pub const IssueLog = report_mod.IssueLog;
51 pub const Mode = allocator_mod.Mode;
52 pub const Report = allocator_mod.Report;
53 pub const RepairPolicy = exterminator_mod.RepairPolicy;
54 pub const RepairTable = exterminator_mod.RepairTable;
55 pub const class_sizes = allocator_mod.class_sizes;
56 pub const max_issues = report_mod.max_issues;
57 pub const max_repair_entries = exterminator_mod.max_repair_entries;
58 pub const max_small_size = allocator_mod.max_small_size;
59 pub const min_alignment = allocator_mod.min_alignment;
60 pub const page_size = allocator_mod.page_size;