infix
A JIT-Powered FFI Library for C
Loading...
Searching...
No Matches
arena.c
Go to the documentation of this file.
1
31#include <stdint.h> // For uintptr_t, SIZE_MAX
32#include <stdlib.h>
33#include <string.h> // For memset
34
35/*
36 * Implementation for infix_arena_create.
37 * This function allocates two separate blocks of memory: one for the `infix_arena_t`
38 * controller struct itself, and a second, larger block for the arena's main buffer.
39 * It includes logic to prevent memory leaks if the second allocation fails.
40 */
41infix_arena_t * infix_arena_create(size_t initial_size) {
42 // Allocate the arena controller struct itself.
44 if (arena == nullptr)
45 return nullptr;
46
47 // Allocate the main memory block for the arena.
48 arena->buffer = infix_malloc(initial_size);
49 if (arena->buffer == nullptr && initial_size > 0) {
50 // Critical cleanup: if the main buffer allocation fails, we must free
51 // the `arena` struct itself to prevent a memory leak.
53 return nullptr;
54 }
55
56 arena->capacity = initial_size;
58 arena->error = false;
59
60 return arena;
61}
62
63/*
64 * Implementation for infix_arena_destroy.
65 * This function frees the main memory buffer and then the `infix_arena_t` struct.
66 * It is safe to call with a `nullptr` argument.
67 */
69 if (arena == nullptr)
70 return;
71
72 // Free the main buffer first, then the controller struct.
73 if (arena->buffer)
75
77}
78
79/*
80 * Implementation for infix_arena_alloc.
81 * This is the core "bump" allocation logic. It calculates the necessary padding
82 * to align the current offset and performs multiple security checks to prevent
83 * integer overflows. If the request fits, it advances the `current_offset` and
84 * returns the aligned pointer; otherwise, it sets the arena's error flag.
85 */
86void * infix_arena_alloc(infix_arena_t * arena, size_t size, size_t alignment) {
87 // Fail immediately if the arena is null or already in an error state.
88 if (arena == nullptr || arena->error)
89 return nullptr;
90
91 // Security: Alignment must be a power of two. This is a common and critical check.
92 if (alignment == 0 || (alignment & (alignment - 1)) != 0) {
93 arena->error = true;
94 return nullptr;
95 }
96
97 // Per the C standard, an allocation of zero bytes should return a valid, unique pointer.
98 // We return a pointer to the current position without advancing the offset.
99 if (size == 0)
100 return (void *)(arena->buffer + arena->current_offset);
101
102 // Calculate the next aligned offset using the shared helper.
103 size_t aligned_offset = _infix_align_up(arena->current_offset, alignment);
104
105 // Security: Check for integer overflow during the alignment calculation.
106 if (aligned_offset < arena->current_offset) {
107 arena->error = true;
108 return nullptr;
109 }
110
111 // Security: Check if adding the requested size would overflow size_t or exceed capacity.
112 if (SIZE_MAX - size < aligned_offset || aligned_offset + size > arena->capacity) {
113 arena->error = true;
114 return nullptr;
115 }
116
117 // All checks passed. Get the pointer and "bump" the offset.
118 void * ptr = arena->buffer + aligned_offset;
119 arena->current_offset = aligned_offset + size;
120 return ptr;
121}
122
123/*
124 * Implementation for infix_arena_calloc.
125 * This is a convenience wrapper around `infix_arena_alloc` that also zeroes the memory.
126 * It includes a critical security check to prevent integer overflow when calculating
127 * the total allocation size.
128 */
129void * infix_arena_calloc(infix_arena_t * arena, size_t num, size_t size, size_t alignment) {
130 // Security: Check for integer overflow in the `num * size` calculation.
131 if (size > 0 && num > SIZE_MAX / size) {
132 if (arena)
133 arena->error = true;
134 return nullptr;
135 }
136
137 size_t total_size = num * size;
138 void * ptr = infix_arena_alloc(arena, total_size, alignment);
139
140 // If allocation was successful, zero out the memory.
141 if (ptr != nullptr)
142 memset(ptr, 0, total_size);
143
144 return ptr;
145}
infix_arena_t * arena
Definition 005_layouts.c:57
#define infix_free
A macro for the memory deallocation function.
Definition infix.h:280
void infix_arena_destroy(infix_arena_t *arena)
Frees an entire memory arena and all objects allocated within it.
Definition arena.c:68
void * infix_arena_calloc(infix_arena_t *arena, size_t num, size_t size, size_t alignment)
Allocates a zero-initialized block of memory from the arena.
Definition arena.c:129
void * infix_arena_alloc(infix_arena_t *arena, size_t size, size_t alignment)
Allocates a block of memory from the arena with a specific alignment.
Definition arena.c:86
#define infix_malloc
A macro for the memory allocation function used by the library.
Definition infix.h:250
infix_arena_t * infix_arena_create(size_t initial_size)
Creates and initializes a new memory arena.
Definition arena.c:41
Declarations for internal-only functions, types, and constants.
static size_t _infix_align_up(size_t value, size_t alignment)
Definition infix_internals.h:383
Definition infix_internals.h:130
char * buffer
The pointer to the large, pre-allocated memory block.
Definition infix_internals.h:131
bool error
A sticky flag that is set if any allocation from this arena fails.
Definition infix_internals.h:134
size_t capacity
The total size of the buffer in bytes.
Definition infix_internals.h:132
size_t current_offset
The high-water mark; the offset of the next free byte.
Definition infix_internals.h:133