authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-30 16:10:20-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-30 16:10:20-07:00
log3f3003097cbf5a6ad9e0dfc29b2cafbe2e35dded
tree2dfd831099a3f3b99039474d164f008243b3ae55
parent9b54c9dee8a571f1c821b3eb4ee3d2c713cf63fa

std.heap.PageAllocator: add check for large allocation

Instead of making the memory alignment functions more complicated, I added more API documentation for their existing semantics. closes #12118 closes #12135

3 files changed, 13 insertions(+), 0 deletions(-)

lib/std/heap.zig+3
...@@ -260,6 +260,9 @@ const PageAllocator = struct {...@@ -260,6 +260,9 @@ const PageAllocator = struct {
260 fn alloc(_: *anyopaque, n: usize, alignment: u29, len_align: u29, ra: usize) error{OutOfMemory}![]u8 {260 fn alloc(_: *anyopaque, n: usize, alignment: u29, len_align: u29, ra: usize) error{OutOfMemory}![]u8 {
261 _ = ra;261 _ = ra;
262 assert(n > 0);262 assert(n > 0);
263 if (n > maxInt(usize) - (mem.page_size - 1)) {
264 return error.OutOfMemory;
265 }
263 const aligned_len = mem.alignForward(n, mem.page_size);266 const aligned_len = mem.alignForward(n, mem.page_size);
264267
265 if (builtin.os.tag == .windows) {268 if (builtin.os.tag == .windows) {
lib/std/heap/general_purpose_allocator.zig+8
...@@ -971,6 +971,14 @@ test "large allocations" {...@@ -971,6 +971,14 @@ test "large allocations" {
971 allocator.free(ptr2);971 allocator.free(ptr2);
972}972}
973973
974test "very large allocation" {
975 var gpa = GeneralPurposeAllocator(test_config){};
976 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
977 const allocator = gpa.allocator();
978
979 try std.testing.expectError(error.OutOfMemory, allocator.alloc(u8, math.maxInt(usize)));
980}
981
974test "realloc" {982test "realloc" {
975 var gpa = GeneralPurposeAllocator(test_config){};983 var gpa = GeneralPurposeAllocator(test_config){};
976 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");984 defer std.testing.expect(!gpa.deinit()) catch @panic("leak");
lib/std/mem.zig+2
...@@ -3551,12 +3551,14 @@ test "sliceAsBytes preserves pointer attributes" {...@@ -3551,12 +3551,14 @@ test "sliceAsBytes preserves pointer attributes" {
35513551
3552/// Round an address up to the next (or current) aligned address.3552/// Round an address up to the next (or current) aligned address.
3553/// The alignment must be a power of 2 and greater than 0.3553/// The alignment must be a power of 2 and greater than 0.
3554/// Asserts that rounding up the address does not cause integer overflow.
3554pub fn alignForward(addr: usize, alignment: usize) usize {3555pub fn alignForward(addr: usize, alignment: usize) usize {
3555 return alignForwardGeneric(usize, addr, alignment);3556 return alignForwardGeneric(usize, addr, alignment);
3556}3557}
35573558
3558/// Round an address up to the next (or current) aligned address.3559/// Round an address up to the next (or current) aligned address.
3559/// The alignment must be a power of 2 and greater than 0.3560/// The alignment must be a power of 2 and greater than 0.
3561/// Asserts that rounding up the address does not cause integer overflow.
3560pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T {3562pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T {
3561 return alignBackwardGeneric(T, addr + (alignment - 1), alignment);3563 return alignBackwardGeneric(T, addr + (alignment - 1), alignment);
3562}3564}