From 0e0f0c9625c5517856883e506f572395d5fac58d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 4 Feb 2025 23:12:55 -0800 Subject: [PATCH] std.heap.GeneralPurposeAllocator: check canary in free --- lib/std/heap/general_purpose_allocator.zig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/std/heap/general_purpose_allocator.zig b/lib/std/heap/general_purpose_allocator.zig index 1fdb09cb41..accdb11457 100644 --- a/lib/std/heap/general_purpose_allocator.zig +++ b/lib/std/heap/general_purpose_allocator.zig @@ -162,6 +162,10 @@ pub const Config = struct { /// Tell whether the backing allocator returns already-zeroed memory. backing_allocator_zeroes: bool = true, + + /// Magic value that distinguishes allocations owned by this allocator from + /// other regions of memory. + canary: usize = @truncate(0x9232a6ff85dff10f), }; pub const Check = enum { ok, leak }; @@ -266,6 +270,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { allocated_count: SlotIndex, freed_count: SlotIndex, prev: ?*BucketHeader, + canary: usize = config.canary, fn fromPage(page_addr: usize, slot_count: usize) *BucketHeader { const unaligned = page_addr + page_size - bucketSize(slot_count); @@ -832,6 +837,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type { const freed_addr = @intFromPtr(old_memory.ptr); const page_addr = freed_addr & ~(page_size - 1); const bucket: *BucketHeader = .fromPage(page_addr, slot_count); + if (bucket.canary != config.canary) @panic("Invalid free"); const page_offset = freed_addr - page_addr; const size_class = @as(usize, 1) << @as(u6, @intCast(size_class_index)); const slot_index: SlotIndex = @intCast(page_offset / size_class);