authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-11 19:41:37-08:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-02-12 13:14:51-08:00
log5c59a4623898cdb15b569f59fba49d48a7b9600f
tree226cfe3efb7ea056e2c914cd6a8953076ca5e7a8
parent0a61eca22c5628b0a56d875246fc4ef007a3bad9

std.heap.PageAllocator: fix not respecting alignments

in remap and resize, alignments larger than page size were incorrectly ignored.

2 files changed, 21 insertions(+), 24 deletions(-)

lib/std/heap/PageAllocator.zig+19-22
......@@ -1,19 +1,17 @@
1const std = @import("../std.zig");
21const builtin = @import("builtin");
2const native_os = builtin.os.tag;
3
4const std = @import("../std.zig");
35const Allocator = std.mem.Allocator;
6const Alignment = std.mem.Alignment;
47const mem = std.mem;
58const maxInt = std.math.maxInt;
69const assert = std.debug.assert;
7const native_os = builtin.os.tag;
810const windows = std.os.windows;
9const ntdll = windows.ntdll;
11const ntdll = std.os.windows.ntdll;
1012const posix = std.posix;
1113const page_size_min = std.heap.page_size_min;
1214
13const SUCCESS = @import("../os/windows/ntstatus.zig").NTSTATUS.SUCCESS;
14const MEM_RESERVE_PLACEHOLDER = windows.MEM_RESERVE_PLACEHOLDER;
15const MEM_PRESERVE_PLACEHOLDER = windows.MEM_PRESERVE_PLACEHOLDER;
16
1715pub const vtable: Allocator.VTable = .{
1816 .alloc = alloc,
1917 .resize = resize,
......@@ -21,7 +19,7 @@ pub const vtable: Allocator.VTable = .{
2119 .free = free,
2220};
2321
24pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
22pub fn map(n: usize, alignment: Alignment) ?[*]u8 {
2523 const page_size = std.heap.pageSize();
2624 if (n >= maxInt(usize) - page_size) return null;
2725 const alignment_bytes = alignment.toByteUnits();
......@@ -33,11 +31,11 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
3331 const current_process = windows.GetCurrentProcess();
3432 var status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .COMMIT = true, .RESERVE = true }, .{ .READWRITE = true });
3533
36 if (status == SUCCESS and mem.isAligned(@intFromPtr(base_addr), alignment_bytes)) {
34 if (status == .SUCCESS and mem.isAligned(@intFromPtr(base_addr), alignment_bytes)) {
3735 return @ptrCast(base_addr);
3836 }
3937
40 if (status == SUCCESS) {
38 if (status == .SUCCESS) {
4139 var region_size: windows.SIZE_T = 0;
4240 _ = ntdll.NtFreeVirtualMemory(current_process, @ptrCast(&base_addr), &region_size, .{ .RELEASE = true });
4341 }
......@@ -50,7 +48,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
5048
5149 status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .RESERVE = true, .RESERVE_PLACEHOLDER = true }, .{ .NOACCESS = true });
5250
53 if (status != SUCCESS) return null;
51 if (status != .SUCCESS) return null;
5452
5553 const placeholder_addr = @intFromPtr(base_addr);
5654 const aligned_addr = mem.alignForward(usize, placeholder_addr, alignment_bytes);
......@@ -75,7 +73,7 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
7573
7674 status = ntdll.NtAllocateVirtualMemory(current_process, @ptrCast(&base_addr), 0, &size, .{ .COMMIT = true }, .{ .READWRITE = true });
7775
78 if (status == SUCCESS) {
76 if (status == .SUCCESS) {
7977 return @ptrCast(base_addr);
8078 }
8179
......@@ -116,31 +114,29 @@ pub fn map(n: usize, alignment: mem.Alignment) ?[*]u8 {
116114 return result_ptr;
117115}
118116
119fn alloc(context: *anyopaque, n: usize, alignment: mem.Alignment, ra: usize) ?[*]u8 {
117fn alloc(context: *anyopaque, n: usize, alignment: Alignment, ra: usize) ?[*]u8 {
120118 _ = context;
121119 _ = ra;
122120 assert(n > 0);
123121 return map(n, alignment);
124122}
125123
126fn resize(context: *anyopaque, memory: []u8, alignment: mem.Alignment, new_len: usize, return_address: usize) bool {
124fn resize(context: *anyopaque, memory: []u8, alignment: Alignment, new_len: usize, return_address: usize) bool {
127125 _ = context;
128 _ = alignment;
129126 _ = return_address;
130 return realloc(memory, new_len, false) != null;
127 return realloc(memory, alignment, new_len, false) != null;
131128}
132129
133fn remap(context: *anyopaque, memory: []u8, alignment: mem.Alignment, new_len: usize, return_address: usize) ?[*]u8 {
130fn remap(context: *anyopaque, memory: []u8, alignment: Alignment, new_len: usize, return_address: usize) ?[*]u8 {
134131 _ = context;
135 _ = alignment;
136132 _ = return_address;
137 return realloc(memory, new_len, true);
133 return realloc(memory, alignment, new_len, true);
138134}
139135
140fn free(context: *anyopaque, memory: []u8, alignment: mem.Alignment, return_address: usize) void {
136fn free(context: *anyopaque, memory: []u8, alignment: Alignment, return_address: usize) void {
141137 _ = context;
142 _ = alignment;
143138 _ = return_address;
139 _ = alignment;
144140 return unmap(@alignCast(memory));
145141}
146142
......@@ -155,9 +151,10 @@ pub fn unmap(memory: []align(page_size_min) u8) void {
155151 }
156152}
157153
158pub fn realloc(uncasted_memory: []u8, new_len: usize, may_move: bool) ?[*]u8 {
154pub fn realloc(uncasted_memory: []u8, alignment: Alignment, new_len: usize, may_move: bool) ?[*]u8 {
159155 const memory: []align(page_size_min) u8 = @alignCast(uncasted_memory);
160156 const page_size = std.heap.pageSize();
157 if (alignment.toByteUnits() > page_size) return null;
161158 const new_size_aligned = mem.alignForward(usize, new_len, page_size);
162159
163160 if (native_os == .windows) {
lib/std/heap/SmpAllocator.zig+2-2
......@@ -179,7 +179,7 @@ fn resize(context: *anyopaque, memory: []u8, alignment: mem.Alignment, new_len:
179179 const new_class = sizeClassIndex(new_len, alignment);
180180 if (class >= size_class_count) {
181181 if (new_class < size_class_count) return false;
182 return PageAllocator.realloc(memory, new_len, false) != null;
182 return PageAllocator.realloc(memory, alignment, new_len, false) != null;
183183 }
184184 return new_class == class;
185185}
......@@ -191,7 +191,7 @@ fn remap(context: *anyopaque, memory: []u8, alignment: mem.Alignment, new_len: u
191191 const new_class = sizeClassIndex(new_len, alignment);
192192 if (class >= size_class_count) {
193193 if (new_class < size_class_count) return null;
194 return PageAllocator.realloc(memory, new_len, true);
194 return PageAllocator.realloc(memory, alignment, new_len, true);
195195 }
196196 return if (new_class == class) memory.ptr else null;
197197}