authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-08-29 20:51:30+02:00
committergravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2020-08-29 20:51:30+02:00
logf20305d249af89d266fc87b353164e2e7c056580
tree51dc687e82562ea3009eb8c7ea17dbee8afb2b96
parent00301bbdd3d8e5df3ac147353e7cc9c67f65901f

gpa: Fix bookkeeping logic

The backing allocator may return a block that's actually bigger than the one required by the user, use the correct quantity when keeping track of the allocation ceiling. Closes #6049

1 files changed, 27 insertions(+), 25 deletions(-)

lib/std/heap/general_purpose_allocator.zig+27-25
......@@ -567,38 +567,40 @@ pub fn GeneralPurposeAllocator(comptime config: Config) type {
567567 const held = self.mutex.acquire();
568568 defer held.release();
569569
570 const prev_req_bytes = self.total_requested_bytes;
570 const new_aligned_size = math.max(len, ptr_align);
571 const mem_slice = blk: {
572 if (new_aligned_size > largest_bucket_object_size) {
573 try self.large_allocations.ensureCapacity(
574 self.backing_allocator,
575 self.large_allocations.entries.items.len + 1,
576 );
577
578 const slice = try self.backing_allocator.allocFn(self.backing_allocator, len, ptr_align, len_align, ret_addr);
579
580 const gop = self.large_allocations.getOrPutAssumeCapacity(@ptrToInt(slice.ptr));
581 assert(!gop.found_existing); // This would mean the kernel double-mapped pages.
582 gop.entry.value.bytes = slice;
583 collectStackTrace(ret_addr, &gop.entry.value.stack_addresses);
584
585 break :blk slice;
586 } else {
587 const new_size_class = math.ceilPowerOfTwoAssert(usize, new_aligned_size);
588 const ptr = try self.allocSlot(new_size_class, ret_addr);
589 break :blk ptr[0..len];
590 }
591 };
592
571593 if (config.enable_memory_limit) {
572 const new_req_bytes = prev_req_bytes + len;
594 // The backing allocator may return a memory block bigger than
595 // `len`, use the effective size for bookkeeping purposes
596 const new_req_bytes = self.total_requested_bytes + mem_slice.len;
573597 if (new_req_bytes > self.requested_memory_limit) {
574598 return error.OutOfMemory;
575599 }
576600 self.total_requested_bytes = new_req_bytes;
577601 }
578 errdefer if (config.enable_memory_limit) {
579 self.total_requested_bytes = prev_req_bytes;
580 };
581
582 const new_aligned_size = math.max(len, ptr_align);
583 if (new_aligned_size > largest_bucket_object_size) {
584 try self.large_allocations.ensureCapacity(
585 self.backing_allocator,
586 self.large_allocations.entries.items.len + 1,
587 );
588602
589 const slice = try self.backing_allocator.allocFn(self.backing_allocator, len, ptr_align, len_align, ret_addr);
590
591 const gop = self.large_allocations.getOrPutAssumeCapacity(@ptrToInt(slice.ptr));
592 assert(!gop.found_existing); // This would mean the kernel double-mapped pages.
593 gop.entry.value.bytes = slice;
594 collectStackTrace(ret_addr, &gop.entry.value.stack_addresses);
595
596 return slice;
597 } else {
598 const new_size_class = math.ceilPowerOfTwoAssert(usize, new_aligned_size);
599 const ptr = try self.allocSlot(new_size_class, ret_addr);
600 return ptr[0..len];
601 }
603 return mem_slice;
602604 }
603605
604606 fn createBucket(self: *Self, size_class: usize, bucket_index: usize) Error!*BucketHeader {