authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-04-04 22:12:32-04:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-04-05 08:23:07+02:00
logad5fb4879b03267f196004a78762de7be3b03de7
tree41e45bbe941ad1fd1f904df2bb7fcad9ad772d73
parenta503724801e7b221aababd88aefe790a33c4135e

std: fix memory bugs

This fixes logged errors during CI based on the new GPA checks.

2 files changed, 30 insertions(+), 31 deletions(-)

lib/std/fs/path.zig+7-9
......@@ -1088,21 +1088,19 @@ pub fn relativeWindows(allocator: Allocator, from: []const u8, to: []const u8) !
10881088 if (ascii.eqlIgnoreCase(from_component, to_component))
10891089 continue;
10901090 }
1091 var up_count: usize = 1;
1091 var up_index_end = "..".len;
10921092 while (from_it.next()) |_| {
1093 up_count += 1;
1093 up_index_end += "\\..".len;
10941094 }
1095 const up_index_end = up_count * "..\\".len;
1096 const result = try allocator.alloc(u8, up_index_end + to_rest.len);
1095 const result = try allocator.alloc(u8, up_index_end + @boolToInt(to_rest.len > 0) + to_rest.len);
10971096 errdefer allocator.free(result);
10981097
1099 var result_index: usize = 0;
1098 result[0..2].* = "..".*;
1099 var result_index: usize = 2;
11001100 while (result_index < up_index_end) {
1101 result[result_index..][0..3].* = "..\\".*;
1101 result[result_index..][0..3].* = "\\..".*;
11021102 result_index += 3;
11031103 }
1104 // shave off the trailing slash
1105 result_index -= 1;
11061104
11071105 var rest_it = mem.tokenize(u8, to_rest, "/\\");
11081106 while (rest_it.next()) |to_component| {
......@@ -1112,7 +1110,7 @@ pub fn relativeWindows(allocator: Allocator, from: []const u8, to: []const u8) !
11121110 result_index += to_component.len;
11131111 }
11141112
1115 return result[0..result_index];
1113 return allocator.realloc(result, result_index);
11161114 }
11171115
11181116 return [_]u8{};
lib/std/heap/arena_allocator.zig+23-22
......@@ -12,7 +12,7 @@ pub const ArenaAllocator = struct {
1212 /// Inner state of ArenaAllocator. Can be stored rather than the entire ArenaAllocator
1313 /// as a memory-saving optimization.
1414 pub const State = struct {
15 buffer_list: std.SinglyLinkedList([]u8) = @as(std.SinglyLinkedList([]u8), .{}),
15 buffer_list: std.SinglyLinkedList(usize) = .{},
1616 end_index: usize = 0,
1717
1818 pub fn promote(self: State, child_allocator: Allocator) ArenaAllocator {
......@@ -34,7 +34,7 @@ pub const ArenaAllocator = struct {
3434 };
3535 }
3636
37 const BufNode = std.SinglyLinkedList([]u8).Node;
37 const BufNode = std.SinglyLinkedList(usize).Node;
3838
3939 pub fn init(child_allocator: Allocator) ArenaAllocator {
4040 return (State{}).promote(child_allocator);
......@@ -47,7 +47,9 @@ pub const ArenaAllocator = struct {
4747 while (it) |node| {
4848 // this has to occur before the free because the free frees node
4949 const next_it = node.next;
50 self.child_allocator.free(node.data);
50 const align_bits = std.math.log2_int(usize, @alignOf(BufNode));
51 const alloc_buf = @ptrCast([*]u8, node)[0..node.data];
52 self.child_allocator.rawFree(alloc_buf, align_bits, @returnAddress());
5153 it = next_it;
5254 }
5355 }
......@@ -73,7 +75,7 @@ pub const ArenaAllocator = struct {
7375 while (it) |node| : (it = node.next) {
7476 // Compute the actually allocated size excluding the
7577 // linked list node.
76 size += node.data.len - @sizeOf(BufNode);
78 size += node.data - @sizeOf(BufNode);
7779 }
7880 return size;
7981 }
......@@ -121,6 +123,7 @@ pub const ArenaAllocator = struct {
121123 .retain_with_limit => |limit| std.math.min(limit, current_capacity),
122124 .free_all => unreachable,
123125 };
126 const align_bits = std.math.log2_int(usize, @alignOf(BufNode));
124127 // Free all nodes except for the last one
125128 var it = self.state.buffer_list.first;
126129 const maybe_first_node = while (it) |node| {
......@@ -128,7 +131,8 @@ pub const ArenaAllocator = struct {
128131 const next_it = node.next;
129132 if (next_it == null)
130133 break node;
131 self.child_allocator.free(node.data);
134 const alloc_buf = @ptrCast([*]u8, node)[0..node.data];
135 self.child_allocator.rawFree(alloc_buf, align_bits, @returnAddress());
132136 it = next_it;
133137 } else null;
134138 std.debug.assert(maybe_first_node == null or maybe_first_node.?.next == null);
......@@ -136,23 +140,21 @@ pub const ArenaAllocator = struct {
136140 self.state.end_index = 0;
137141 if (maybe_first_node) |first_node| {
138142 // perfect, no need to invoke the child_allocator
139 if (first_node.data.len == total_size)
143 if (first_node.data == total_size)
140144 return true;
141 const align_bits = std.math.log2_int(usize, @alignOf(BufNode));
142 if (self.child_allocator.rawResize(first_node.data, align_bits, total_size, @returnAddress())) {
145 const first_alloc_buf = @ptrCast([*]u8, first_node)[0..first_node.data];
146 if (self.child_allocator.rawResize(first_alloc_buf, align_bits, total_size, @returnAddress())) {
143147 // successful resize
144 first_node.data.len = total_size;
148 first_node.data = total_size;
145149 } else {
146150 // manual realloc
147151 const new_ptr = self.child_allocator.rawAlloc(total_size, align_bits, @returnAddress()) orelse {
148152 // we failed to preheat the arena properly, signal this to the user.
149153 return false;
150154 };
151 self.child_allocator.rawFree(first_node.data, align_bits, @returnAddress());
155 self.child_allocator.rawFree(first_alloc_buf, align_bits, @returnAddress());
152156 const node = @ptrCast(*BufNode, @alignCast(@alignOf(BufNode), new_ptr));
153 node.* = BufNode{
154 .data = new_ptr[0..total_size],
155 };
157 node.* = .{ .data = total_size };
156158 self.state.buffer_list.first = node;
157159 }
158160 }
......@@ -167,10 +169,7 @@ pub const ArenaAllocator = struct {
167169 const ptr = self.child_allocator.rawAlloc(len, log2_align, @returnAddress()) orelse
168170 return null;
169171 const buf_node = @ptrCast(*BufNode, @alignCast(@alignOf(BufNode), ptr));
170 buf_node.* = BufNode{
171 .data = ptr[0..len],
172 .next = null,
173 };
172 buf_node.* = .{ .data = len };
174173 self.state.buffer_list.prepend(buf_node);
175174 self.state.end_index = 0;
176175 return buf_node;
......@@ -186,7 +185,8 @@ pub const ArenaAllocator = struct {
186185 else
187186 (self.createNode(0, n + ptr_align) orelse return null);
188187 while (true) {
189 const cur_buf = cur_node.data[@sizeOf(BufNode)..];
188 const cur_alloc_buf = @ptrCast([*]u8, cur_node)[0..cur_node.data];
189 const cur_buf = cur_alloc_buf[@sizeOf(BufNode)..];
190190 const addr = @ptrToInt(cur_buf.ptr) + self.state.end_index;
191191 const adjusted_addr = mem.alignForward(addr, ptr_align);
192192 const adjusted_index = self.state.end_index + (adjusted_addr - addr);
......@@ -199,8 +199,9 @@ pub const ArenaAllocator = struct {
199199 }
200200
201201 const bigger_buf_size = @sizeOf(BufNode) + new_end_index;
202 if (self.child_allocator.resize(cur_node.data, bigger_buf_size)) {
203 cur_node.data.len = bigger_buf_size;
202 const log2_align = comptime std.math.log2_int(usize, @alignOf(BufNode));
203 if (self.child_allocator.rawResize(cur_alloc_buf, log2_align, bigger_buf_size, @returnAddress())) {
204 cur_node.data = bigger_buf_size;
204205 } else {
205206 // Allocate a new node if that's not possible
206207 cur_node = self.createNode(cur_buf.len, n + ptr_align) orelse return null;
......@@ -214,7 +215,7 @@ pub const ArenaAllocator = struct {
214215 _ = ret_addr;
215216
216217 const cur_node = self.state.buffer_list.first orelse return false;
217 const cur_buf = cur_node.data[@sizeOf(BufNode)..];
218 const cur_buf = @ptrCast([*]u8, cur_node)[@sizeOf(BufNode)..cur_node.data];
218219 if (@ptrToInt(cur_buf.ptr) + self.state.end_index != @ptrToInt(buf.ptr) + buf.len) {
219220 // It's not the most recent allocation, so it cannot be expanded,
220221 // but it's fine if they want to make it smaller.
......@@ -239,7 +240,7 @@ pub const ArenaAllocator = struct {
239240 const self = @ptrCast(*ArenaAllocator, @alignCast(@alignOf(ArenaAllocator), ctx));
240241
241242 const cur_node = self.state.buffer_list.first orelse return;
242 const cur_buf = cur_node.data[@sizeOf(BufNode)..];
243 const cur_buf = @ptrCast([*]u8, cur_node)[@sizeOf(BufNode)..cur_node.data];
243244
244245 if (@ptrToInt(cur_buf.ptr) + self.state.end_index == @ptrToInt(buf.ptr) + buf.len) {
245246 self.state.end_index -= buf.len;