Skip to content

Commit e8618bc

Browse files
committed
std: fix sentinel handling in Allocator interface
Currently the only function that handles sentinel terminated slices properly is free. All other uses of mem.sliceAsBytes() in the allocator interface lack proper handling of a possible sentinel. This commit changes the Allocator interface to use @ptrCast() plus the new mem.absorbSentinel() instead. This also makes incorrectly passing a pointer to array to Allocator.free() a compile error. The proper function to free a pointer to an array is Allocator.destroy(). Reported-by: David Vanderson <[email protected]> References: #19984 References: #22706 References: #23020
1 parent 7af533f commit e8618bc

File tree

1 file changed

+7
-9
lines changed

1 file changed

+7
-9
lines changed

lib/std/mem/Allocator.zig

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
290290
if (allocation.len == 0) {
291291
return false;
292292
}
293-
const old_memory = mem.sliceAsBytes(allocation);
293+
const old_memory: []u8 = @constCast(@ptrCast(mem.absorbSentinel(allocation)));
294294
// I would like to use saturating multiplication here, but LLVM cannot lower it
295295
// on WebAssembly: https://github.com/ziglang/zig/issues/9660
296296
//const new_len_bytes = new_len *| @sizeOf(T);
@@ -325,7 +325,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {
325325
if (allocation.len == 0) {
326326
return null;
327327
}
328-
const old_memory = mem.sliceAsBytes(allocation);
328+
const old_memory: []u8 = @constCast(@ptrCast(mem.absorbSentinel(allocation)));
329329
// I would like to use saturating multiplication here, but LLVM cannot lower it
330330
// on WebAssembly: https://github.com/ziglang/zig/issues/9660
331331
//const new_len_bytes = new_len *| @sizeOf(T);
@@ -374,7 +374,7 @@ pub fn reallocAdvanced(
374374
return @as([*]align(Slice.alignment) T, @ptrFromInt(ptr))[0..0];
375375
}
376376

377-
const old_byte_slice = mem.sliceAsBytes(old_mem);
377+
const old_byte_slice: []u8 = @constCast(@ptrCast(mem.absorbSentinel(old_mem)));
378378
const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory;
379379
// Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure
380380
if (self.rawRemap(old_byte_slice, .fromByteUnits(Slice.alignment), byte_count, return_address)) |p| {
@@ -398,12 +398,10 @@ pub fn reallocAdvanced(
398398
/// To free a single item, see `destroy`.
399399
pub fn free(self: Allocator, memory: anytype) void {
400400
const Slice = @typeInfo(@TypeOf(memory)).pointer;
401-
const bytes = mem.sliceAsBytes(memory);
402-
const bytes_len = bytes.len + if (Slice.sentinel() != null) @sizeOf(Slice.child) else 0;
403-
if (bytes_len == 0) return;
404-
const non_const_ptr = @constCast(bytes.ptr);
405-
@memset(non_const_ptr[0..bytes_len], undefined);
406-
self.rawFree(non_const_ptr[0..bytes_len], .fromByteUnits(Slice.alignment), @returnAddress());
401+
const bytes: []u8 = @constCast(@ptrCast(mem.absorbSentinel(memory)));
402+
if (bytes.len == 0) return;
403+
@memset(bytes, undefined);
404+
self.rawFree(bytes, .fromByteUnits(Slice.alignment), @returnAddress());
407405
}
408406

409407
/// Copies `m` to newly allocated memory. Caller owns the memory.

0 commit comments

Comments
 (0)