Skip to content

Commit 7099274

Browse files
ifreundmlugg
authored andcommitted
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: ziglang#19984 References: ziglang#22706 References: ziglang#23020
1 parent 3b25a09 commit 7099274

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
@@ -304,7 +304,7 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool {
304304
if (allocation.len == 0) {
305305
return false;
306306
}
307-
const old_memory = mem.sliceAsBytes(allocation);
307+
const old_memory: []u8 = @constCast(@ptrCast(mem.absorbSentinel(allocation)));
308308
// I would like to use saturating multiplication here, but LLVM cannot lower it
309309
// on WebAssembly: https://github.com/ziglang/zig/issues/9660
310310
//const new_len_bytes = new_len *| @sizeOf(T);
@@ -348,7 +348,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {
348348
new_memory.len = new_len;
349349
return new_memory;
350350
}
351-
const old_memory = mem.sliceAsBytes(allocation);
351+
const old_memory: []u8 = @constCast(@ptrCast(mem.absorbSentinel(allocation)));
352352
// I would like to use saturating multiplication here, but LLVM cannot lower it
353353
// on WebAssembly: https://github.com/ziglang/zig/issues/9660
354354
//const new_len_bytes = new_len *| @sizeOf(T);
@@ -397,7 +397,7 @@ pub fn reallocAdvanced(
397397
return @as([*]align(Slice.alignment) T, @ptrFromInt(ptr))[0..0];
398398
}
399399

400-
const old_byte_slice = mem.sliceAsBytes(old_mem);
400+
const old_byte_slice: []u8 = @constCast(@ptrCast(mem.absorbSentinel(old_mem)));
401401
const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory;
402402
// Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure
403403
if (self.rawRemap(old_byte_slice, .fromByteUnits(Slice.alignment), byte_count, return_address)) |p| {
@@ -421,12 +421,10 @@ pub fn reallocAdvanced(
421421
/// To free a single item, see `destroy`.
422422
pub fn free(self: Allocator, memory: anytype) void {
423423
const Slice = @typeInfo(@TypeOf(memory)).pointer;
424-
const bytes = mem.sliceAsBytes(memory);
425-
const bytes_len = bytes.len + if (Slice.sentinel() != null) @sizeOf(Slice.child) else 0;
426-
if (bytes_len == 0) return;
427-
const non_const_ptr = @constCast(bytes.ptr);
428-
@memset(non_const_ptr[0..bytes_len], undefined);
429-
self.rawFree(non_const_ptr[0..bytes_len], .fromByteUnits(Slice.alignment), @returnAddress());
424+
const bytes: []u8 = @constCast(@ptrCast(mem.absorbSentinel(memory)));
425+
if (bytes.len == 0) return;
426+
@memset(bytes, undefined);
427+
self.rawFree(bytes, .fromByteUnits(Slice.alignment), @returnAddress());
430428
}
431429

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

0 commit comments

Comments
 (0)