aboutsummaryrefslogtreecommitdiff
path: root/core/mem/rollback_stack_allocator.odin
diff options
context:
space:
mode:
authorLucas Perlind <perlindluca@gmail.com>2025-04-30 19:21:00 +1000
committerLucas Perlind <perlindluca@gmail.com>2025-05-06 14:55:50 +1000
commit83bc2d3c4a186d6a8c362eed901acd6bc6363a8d (patch)
treeea5c4b6bccb6aa226e6a3ed8036ae3fd24a1915c /core/mem/rollback_stack_allocator.odin
parent8032db348411ae85397441de7f2ce9ebd1029112 (diff)
Add asan support for various allocators
Diffstat (limited to 'core/mem/rollback_stack_allocator.odin')
-rw-r--r--core/mem/rollback_stack_allocator.odin50
1 files changed, 31 insertions, 19 deletions
diff --git a/core/mem/rollback_stack_allocator.odin b/core/mem/rollback_stack_allocator.odin
index 43ef10fe9..a00131b7f 100644
--- a/core/mem/rollback_stack_allocator.odin
+++ b/core/mem/rollback_stack_allocator.odin
@@ -1,6 +1,7 @@
package mem
import "base:runtime"
+import "base:sanitizer"
/*
Rollback stack default block size.
@@ -47,14 +48,14 @@ Rollback_Stack :: struct {
block_allocator: Allocator,
}
-@(private="file", require_results)
+@(private="file", require_results, no_sanitize_address)
rb_ptr_in_bounds :: proc(block: ^Rollback_Stack_Block, ptr: rawptr) -> bool {
start := raw_data(block.buffer)
end := start[block.offset:]
return start < ptr && ptr <= end
}
-@(private="file", require_results)
+@(private="file", require_results, no_sanitize_address)
rb_find_ptr :: proc(stack: ^Rollback_Stack, ptr: rawptr) -> (
parent: ^Rollback_Stack_Block,
block: ^Rollback_Stack_Block,
@@ -71,7 +72,7 @@ rb_find_ptr :: proc(stack: ^Rollback_Stack, ptr: rawptr) -> (
return nil, nil, nil, .Invalid_Pointer
}
-@(private="file", require_results)
+@(private="file", require_results, no_sanitize_address)
rb_find_last_alloc :: proc(stack: ^Rollback_Stack, ptr: rawptr) -> (
block: ^Rollback_Stack_Block,
header: ^Rollback_Stack_Header,
@@ -86,9 +87,10 @@ rb_find_last_alloc :: proc(stack: ^Rollback_Stack, ptr: rawptr) -> (
return nil, nil, false
}
-@(private="file")
+@(private="file", no_sanitize_address)
rb_rollback_block :: proc(block: ^Rollback_Stack_Block, header: ^Rollback_Stack_Header) {
header := header
+
for block.offset > 0 && header.is_free {
block.offset = header.prev_offset
block.last_alloc = raw_data(block.buffer)[header.prev_ptr:]
@@ -99,9 +101,10 @@ rb_rollback_block :: proc(block: ^Rollback_Stack_Block, header: ^Rollback_Stack_
/*
Free memory to a rollback stack allocator.
*/
-@(private="file", require_results)
+@(private="file", require_results, no_sanitize_address)
rb_free :: proc(stack: ^Rollback_Stack, ptr: rawptr) -> Allocator_Error {
parent, block, header := rb_find_ptr(stack, ptr) or_return
+
if header.is_free {
return .Invalid_Pointer
}
@@ -120,7 +123,7 @@ rb_free :: proc(stack: ^Rollback_Stack, ptr: rawptr) -> Allocator_Error {
/*
Free all memory owned by the rollback stack allocator.
*/
-@(private="file")
+@(private="file", no_sanitize_address)
rb_free_all :: proc(stack: ^Rollback_Stack) {
for block := stack.head.next_block; block != nil; /**/ {
next_block := block.next_block
@@ -131,12 +134,13 @@ rb_free_all :: proc(stack: ^Rollback_Stack) {
stack.head.next_block = nil
stack.head.last_alloc = nil
stack.head.offset = 0
+ sanitizer.address_poison(stack.head.buffer)
}
/*
Allocate memory using the rollback stack allocator.
*/
-@(require_results)
+@(require_results, no_sanitize_address)
rb_alloc :: proc(
stack: ^Rollback_Stack,
size: int,
@@ -153,7 +157,7 @@ rb_alloc :: proc(
/*
Allocate memory using the rollback stack allocator.
*/
-@(require_results)
+@(require_results, no_sanitize_address)
rb_alloc_bytes :: proc(
stack: ^Rollback_Stack,
size: int,
@@ -170,7 +174,7 @@ rb_alloc_bytes :: proc(
/*
Allocate non-initialized memory using the rollback stack allocator.
*/
-@(require_results)
+@(require_results, no_sanitize_address)
rb_alloc_non_zeroed :: proc(
stack: ^Rollback_Stack,
size: int,
@@ -184,7 +188,7 @@ rb_alloc_non_zeroed :: proc(
/*
Allocate non-initialized memory using the rollback stack allocator.
*/
-@(require_results)
+@(require_results, no_sanitize_address)
rb_alloc_bytes_non_zeroed :: proc(
stack: ^Rollback_Stack,
size: int,
@@ -194,6 +198,7 @@ rb_alloc_bytes_non_zeroed :: proc(
assert(size >= 0, "Size must be positive or zero.", loc)
assert(is_power_of_two(cast(uintptr)alignment), "Alignment must be a power of two.", loc)
parent: ^Rollback_Stack_Block
+
for block := stack.head; /**/; block = block.next_block {
when !ODIN_DISABLE_ASSERT {
allocated_new_block: bool
@@ -235,7 +240,9 @@ rb_alloc_bytes_non_zeroed :: proc(
// Prevent any further allocations on it.
block.offset = cast(uintptr)len(block.buffer)
}
- #no_bounds_check return ptr[:size], nil
+ res := ptr[:size]
+ sanitizer.address_unpoison(res)
+ return res, nil
}
return nil, .Out_Of_Memory
}
@@ -243,7 +250,7 @@ rb_alloc_bytes_non_zeroed :: proc(
/*
Resize an allocation owned by rollback stack allocator.
*/
-@(require_results)
+@(require_results, no_sanitize_address)
rb_resize :: proc(
stack: ^Rollback_Stack,
old_ptr: rawptr,
@@ -266,7 +273,7 @@ rb_resize :: proc(
/*
Resize an allocation owned by rollback stack allocator.
*/
-@(require_results)
+@(require_results, no_sanitize_address)
rb_resize_bytes :: proc(
stack: ^Rollback_Stack,
old_memory: []byte,
@@ -289,7 +296,7 @@ rb_resize_bytes :: proc(
Resize an allocation owned by rollback stack allocator without explicit
zero-initialization.
*/
-@(require_results)
+@(require_results, no_sanitize_address)
rb_resize_non_zeroed :: proc(
stack: ^Rollback_Stack,
old_ptr: rawptr,
@@ -306,7 +313,7 @@ rb_resize_non_zeroed :: proc(
Resize an allocation owned by rollback stack allocator without explicit
zero-initialization.
*/
-@(require_results)
+@(require_results, no_sanitize_address)
rb_resize_bytes_non_zeroed :: proc(
stack: ^Rollback_Stack,
old_memory: []byte,
@@ -330,7 +337,9 @@ rb_resize_bytes_non_zeroed :: proc(
if len(block.buffer) <= stack.block_size {
block.offset += cast(uintptr)size - cast(uintptr)old_size
}
- #no_bounds_check return (ptr)[:size], nil
+ res := (ptr)[:size]
+ sanitizer.address_unpoison(res)
+ #no_bounds_check return res, nil
}
}
}
@@ -340,7 +349,7 @@ rb_resize_bytes_non_zeroed :: proc(
return
}
-@(private="file", require_results)
+@(private="file", require_results, no_sanitize_address)
rb_make_block :: proc(size: int, allocator: Allocator) -> (block: ^Rollback_Stack_Block, err: Allocator_Error) {
buffer := runtime.mem_alloc(size_of(Rollback_Stack_Block) + size, align_of(Rollback_Stack_Block), allocator) or_return
block = cast(^Rollback_Stack_Block)raw_data(buffer)
@@ -351,6 +360,7 @@ rb_make_block :: proc(size: int, allocator: Allocator) -> (block: ^Rollback_Stac
/*
Initialize the rollback stack allocator using a fixed backing buffer.
*/
+@(no_sanitize_address)
rollback_stack_init_buffered :: proc(stack: ^Rollback_Stack, buffer: []byte, location := #caller_location) {
MIN_SIZE :: size_of(Rollback_Stack_Block) + size_of(Rollback_Stack_Header) + size_of(rawptr)
assert(len(buffer) >= MIN_SIZE, "User-provided buffer to Rollback Stack Allocator is too small.", location)
@@ -365,6 +375,7 @@ rollback_stack_init_buffered :: proc(stack: ^Rollback_Stack, buffer: []byte, loc
/*
Initialize the rollback stack alocator using a backing block allocator.
*/
+@(no_sanitize_address)
rollback_stack_init_dynamic :: proc(
stack: ^Rollback_Stack,
block_size : int = ROLLBACK_STACK_DEFAULT_BLOCK_SIZE,
@@ -396,6 +407,7 @@ rollback_stack_init :: proc {
/*
Destroy a rollback stack.
*/
+@(no_sanitize_address)
rollback_stack_destroy :: proc(stack: ^Rollback_Stack) {
if stack.block_allocator.procedure != nil {
rb_free_all(stack)
@@ -435,7 +447,7 @@ from the last allocation backwards.
Each allocation has an overhead of 8 bytes and any extra bytes to satisfy
the requested alignment.
*/
-@(require_results)
+@(require_results, no_sanitize_address)
rollback_stack_allocator :: proc(stack: ^Rollback_Stack) -> Allocator {
return Allocator {
data = stack,
@@ -443,7 +455,7 @@ rollback_stack_allocator :: proc(stack: ^Rollback_Stack) -> Allocator {
}
}
-@(require_results)
+@(require_results, no_sanitize_address)
rollback_stack_allocator_proc :: proc(
allocator_data: rawptr,
mode: Allocator_Mode,