- Reallocating overaligned memory with the LibcAllocator was unsafe.

This commit is contained in:
Christoffer Lerno
2026-02-10 11:23:51 +01:00
parent dcbd0f8f2d
commit 7b8299c8dd
2 changed files with 29 additions and 15 deletions

View File

@@ -15,7 +15,6 @@ module std::core::mem::allocator @if(env::POSIX);
import std::os;
import libc;
fn void*? LibcAllocator.acquire(&self, usz bytes, AllocInitType init_type, usz alignment) @dynamic
{
if (init_type == ZERO)
@@ -50,24 +49,38 @@ fn void*? LibcAllocator.acquire(&self, usz bytes, AllocInitType init_type, usz a
fn void*? LibcAllocator.resize(&self, void* old_ptr, usz new_bytes, usz alignment) @dynamic
{
if (alignment <= mem::DEFAULT_MEM_ALIGNMENT) return libc::realloc(old_ptr, new_bytes) ?: mem::OUT_OF_MEMORY~;
void* new_ptr;
if (posix::posix_memalign(&new_ptr, alignment, new_bytes)) return mem::OUT_OF_MEMORY~;
$switch:
$case env::DARWIN:
usz old_usable_size = darwin::malloc_size(old_ptr);
$case env::LINUX:
usz old_usable_size = linux::malloc_usable_size(old_ptr);
$default:
usz old_usable_size = new_bytes;
$endswitch
// Easy case, it's 0
if (!new_bytes)
{
libc::free(old_ptr);
return null;
}
// Try realloc, even though it might be unaligned.
void* new_ptr = libc::realloc(old_ptr, new_bytes) ?: mem::OUT_OF_MEMORY~!;
// If it's aligned then we're done!
uptr ptr_val = (uptr)new_ptr;
if (ptr_val & (alignment - 1) == 0) return new_ptr;
// We failed, so we need to use memalign
// We will free new_ptr before we exit.
defer libc::free(new_ptr);
// Create a pointer which is sure to be aligned.
void* aligned_ptr;
if (posix::posix_memalign(&aligned_ptr, alignment, new_bytes))
{
return mem::OUT_OF_MEMORY~;
}
// Now it is safe to copy the full range of data.
mem::copy(aligned_ptr, old_ptr, new_bytes, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT);
return aligned_ptr;
usz copy_size = new_bytes < old_usable_size ? new_bytes : old_usable_size;
mem::copy(new_ptr, old_ptr, copy_size, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT);
libc::free(old_ptr);
return new_ptr;
}
fn void LibcAllocator.release(&self, void* old_ptr, bool aligned) @dynamic
{
libc::free(old_ptr);

View File

@@ -27,6 +27,7 @@
- Const inline enums would not always implicitly get converted to the underlying type.
- Update to dstring.append_string to take any type converting to String.
- Flag `--cpu-flags` doesn't work if the first item is an exclusion. #2905
- Reallocating overaligned memory with the LibcAllocator was unsafe.
## 0.7.9 Change list