Skip to content

Commit 02e77c9

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 22524f5 commit 02e77c9

File tree

1 file changed

+7
-9
lines changed

1 file changed

+7
-9
lines changed

lib/std/mem/Allocator.zig

+7-9
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);
@@ -334,7 +334,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) t: {
334334
new_memory.len = new_len;
335335
return new_memory;
336336
}
337-
const old_memory = mem.sliceAsBytes(allocation);
337+
const old_memory: []u8 = @constCast(@ptrCast(mem.absorbSentinel(allocation)));
338338
// I would like to use saturating multiplication here, but LLVM cannot lower it
339339
// on WebAssembly: https://github.com/ziglang/zig/issues/9660
340340
//const new_len_bytes = new_len *| @sizeOf(T);
@@ -383,7 +383,7 @@ pub fn reallocAdvanced(
383383
return @as([*]align(Slice.alignment) T, @ptrFromInt(ptr))[0..0];
384384
}
385385

386-
const old_byte_slice = mem.sliceAsBytes(old_mem);
386+
const old_byte_slice: []u8 = @constCast(@ptrCast(mem.absorbSentinel(old_mem)));
387387
const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory;
388388
// Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure
389389
if (self.rawRemap(old_byte_slice, .fromByteUnits(Slice.alignment), byte_count, return_address)) |p| {
@@ -407,12 +407,10 @@ pub fn reallocAdvanced(
407407
/// To free a single item, see `destroy`.
408408
pub fn free(self: Allocator, memory: anytype) void {
409409
const Slice = @typeInfo(@TypeOf(memory)).pointer;
410-
const bytes = mem.sliceAsBytes(memory);
411-
const bytes_len = bytes.len + if (Slice.sentinel() != null) @sizeOf(Slice.child) else 0;
412-
if (bytes_len == 0) return;
413-
const non_const_ptr = @constCast(bytes.ptr);
414-
@memset(non_const_ptr[0..bytes_len], undefined);
415-
self.rawFree(non_const_ptr[0..bytes_len], .fromByteUnits(Slice.alignment), @returnAddress());
410+
const bytes: []u8 = @constCast(@ptrCast(mem.absorbSentinel(memory)));
411+
if (bytes.len == 0) return;
412+
@memset(bytes, undefined);
413+
self.rawFree(bytes, .fromByteUnits(Slice.alignment), @returnAddress());
416414
}
417415

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

0 commit comments

Comments
 (0)