mirror of
https://github.com/odin-lang/Odin.git
synced 2026-08-18 03:12:10 +00:00
base/runtime: do not free the original block on a failed heap resize
`base/runtime`: do not free the original block on a failed heap resize The default heap allocator freed old_ptr when the underlying allocation failed (allocated_mem == nil). On the realloc path (heap_resize) the original block is left intact on failure, and on the copy/fresh path old_ptr has not been copied or freed yet, so freeing it left the caller holding a dangling pointer. A [dynamic] array whose resize failed therefore double-freed its data on the next delete (reported as free(): invalid pointer / use-after-free). Return .Out_Of_Memory without freeing anything; the caller retains ownership of the original block. Fixes #7262
This commit is contained in:
@@ -42,8 +42,10 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
ptr := uintptr(aligned_mem)
|
||||
aligned_ptr := (ptr + uintptr(a)-1) & ~(uintptr(a)-1)
|
||||
if allocated_mem == nil {
|
||||
aligned_free(old_ptr)
|
||||
aligned_free(allocated_mem)
|
||||
// On failure nothing must be freed: heap_resize (realloc) leaves the
|
||||
// original block intact, and on the copy/fresh path old_ptr has not
|
||||
// been copied or freed yet. Freeing old_ptr here left the caller's
|
||||
// pointer dangling, causing a later double free. (#7262)
|
||||
return nil, .Out_Of_Memory
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user