Fix potential overflow when we're nearing 4G blocks..
This commit is contained in:
+51
-7
@@ -1,8 +1,10 @@
|
||||
#include "base_core.h"
|
||||
#include "arena.h"
|
||||
#include "platform.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
void arena_dump(const Arena *arena)
|
||||
{
|
||||
return;
|
||||
@@ -51,8 +53,8 @@ static void arena_test_2(void)
|
||||
TRACEF("\n");
|
||||
|
||||
ArenaOptions arena_params = {};
|
||||
U32 arena_size = MB(1) + MemoryBlock_Header_Size;
|
||||
U32 commit_size = KB(16);
|
||||
U32 arena_size = MB(3) + MemoryBlock_Header_Size;
|
||||
U32 commit_size = KB(72);
|
||||
U32 push_size = KB(32);
|
||||
arena_params.size = arena_size;
|
||||
arena_params.commit_size = commit_size;
|
||||
@@ -66,7 +68,7 @@ static void arena_test_2(void)
|
||||
|
||||
arena_dump(&arena);
|
||||
ArenaCheckpoint checkpoint = arena_temp_begin(&arena);
|
||||
ptr = arena_push(&arena, MB(2), 8);
|
||||
ptr = arena_push(&arena, MB(4)+3, 8);
|
||||
MemoryZero(ptr, MB(2));
|
||||
|
||||
ptr = arena_push(&arena, commit_size * 3, 8);
|
||||
@@ -92,8 +94,10 @@ static void arena_test_2(void)
|
||||
arena_reset_to(&arena, 1089);
|
||||
arena_dump(&arena);
|
||||
arena_reset_to(&arena, 0);
|
||||
ptr = arena_push(&arena, MB(1), 8);
|
||||
MemoryZero(ptr, MB(1));
|
||||
for (U64 i = 0; i < KB(1); i++) {
|
||||
ptr = arena_push(&arena, MB(1) + 3, 8);
|
||||
MemoryZero(ptr, MB(1));
|
||||
}
|
||||
arena_free(&arena);
|
||||
}
|
||||
|
||||
@@ -120,9 +124,49 @@ static void arena_test_3(void)
|
||||
arena_free(&arena);
|
||||
}
|
||||
|
||||
// Exercises the alignment-padding edge case: a fresh block has first_free at
|
||||
// MemoryBlock_Header_Size (64), so a large alignment pushes the user pointer
|
||||
// well past the header. Requesting (block_size - 64) bytes with page alignment
|
||||
// previously tripped the end_pos <= block->size assert because the alignment
|
||||
// gap was not accounted for. After the fix this should allocate a larger block.
|
||||
static void arena_test_4(void)
|
||||
{
|
||||
TRACEF("\n");
|
||||
|
||||
U32 page_size = platform_page_size();
|
||||
ArenaOptions arena_params = {};
|
||||
U32 arena_size = MB(1) + MemoryBlock_Header_Size;
|
||||
U32 commit_size = KB(64);
|
||||
arena_params.size = arena_size;
|
||||
arena_params.commit_size = commit_size;
|
||||
Arena arena;
|
||||
arena_init(&arena, &arena_params);
|
||||
|
||||
// block_size is the page-aligned arena_size. Request nearly the whole block
|
||||
// but with page alignment, so the alignment gap (a full page) forces a grow.
|
||||
U32 block_size = arena.block_size;
|
||||
U32 push_size = block_size - MemoryBlock_Header_Size;
|
||||
|
||||
void *ptr = arena_push(&arena, push_size, page_size);
|
||||
Assert(IsAlignedTo((uintptr_t)ptr, page_size));
|
||||
MemoryZero(ptr, push_size);
|
||||
printf("test_4: allocated %u bytes page-aligned at %p\n", push_size, ptr);
|
||||
arena_dump(&arena);
|
||||
|
||||
// A second page-aligned push to make sure the cursor math still holds.
|
||||
ptr = arena_push(&arena, page_size, page_size);
|
||||
Assert(IsAlignedTo((uintptr_t)ptr, page_size));
|
||||
MemoryZero(ptr, page_size);
|
||||
printf("test_4: allocated %u bytes page-aligned at %p\n", page_size, ptr);
|
||||
|
||||
arena_free(&arena);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
arena_test_1();
|
||||
// arena_test_1();
|
||||
arena_test_2();
|
||||
arena_test_3();
|
||||
// arena_test_3();
|
||||
arena_test_4();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user