authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-04 23:12:55-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-06 14:23:23-08:00
log0e0f0c9625c5517856883e506f572395d5fac58d
tree1285c0989a682fc47c63390ae176bc0ebf3187ce
parent8ff7481e8245f916966973e2c830bc3fb5e4c748

std.heap.GeneralPurposeAllocator: check canary in free


1 files changed, 6 insertions(+), 0 deletions(-)

lib/std/heap/general_purpose_allocator.zig+6
...@@ -162,6 +162,10 @@ pub const Config = struct {...@@ -162,6 +162,10 @@ pub const Config = struct {
162162
163 /// Tell whether the backing allocator returns already-zeroed memory.163 /// Tell whether the backing allocator returns already-zeroed memory.
164 backing_allocator_zeroes: bool = true,164 backing_allocator_zeroes: bool = true,
165
166 /// Magic value that distinguishes allocations owned by this allocator from
167 /// other regions of memory.
168 canary: usize = @truncate(0x9232a6ff85dff10f),
165};169};
166170
167pub const Check = enum { ok, leak };171pub const Check = enum { ok, leak };
...@@ -266,6 +270,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -266,6 +270,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
266 allocated_count: SlotIndex,270 allocated_count: SlotIndex,
267 freed_count: SlotIndex,271 freed_count: SlotIndex,
268 prev: ?*BucketHeader,272 prev: ?*BucketHeader,
273 canary: usize = config.canary,
269274
270 fn fromPage(page_addr: usize, slot_count: usize) *BucketHeader {275 fn fromPage(page_addr: usize, slot_count: usize) *BucketHeader {
271 const unaligned = page_addr + page_size - bucketSize(slot_count);276 const unaligned = page_addr + page_size - bucketSize(slot_count);
...@@ -832,6 +837,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {...@@ -832,6 +837,7 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
832 const freed_addr = @intFromPtr(old_memory.ptr);837 const freed_addr = @intFromPtr(old_memory.ptr);
833 const page_addr = freed_addr & ~(page_size - 1);838 const page_addr = freed_addr & ~(page_size - 1);
834 const bucket: *BucketHeader = .fromPage(page_addr, slot_count);839 const bucket: *BucketHeader = .fromPage(page_addr, slot_count);
840 if (bucket.canary != config.canary) @panic("Invalid free");
835 const page_offset = freed_addr - page_addr;841 const page_offset = freed_addr - page_addr;
836 const size_class = @as(usize, 1) << @as(u6, @intCast(size_class_index));842 const size_class = @as(usize, 1) << @as(u6, @intCast(size_class_index));
837 const slot_index: SlotIndex = @intCast(page_offset / size_class);843 const slot_index: SlotIndex = @intCast(page_offset / size_class);