Skip to content

Commit ccdaa00

Browse files
committed
Correctness fixes and (optional) better C stdlib integration
- Add early NULL check to ta_free() - Add overflow checks in alloc_block() and ta_calloc() - Clear full block size to 0's in ta_calloc() - Optionally set errno to ENOMEM when out of memory - Optionally use memset() to implement memclear() - Add ta_getsize() to return allocated block size - Add ta_realloc() (optional, requires memcpy()) ta_getsize() and ta_realloc() are based on ideas from #11, but rewritten to fix various issues in that PR.
1 parent b60fcd7 commit ccdaa00

File tree

2 files changed

+73
-1
lines changed

2 files changed

+73
-1
lines changed

tinyalloc.c

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ extern void print_i(size_t);
99
#define print_i(X)
1010
#endif
1111

12+
/* optional C stdlib integration */
13+
#ifdef TA_USE_STDLIB
14+
#include <errno.h>
15+
#include <string.h>
16+
#endif
17+
1218
typedef struct Block Block;
1319

1420
struct Block {
@@ -134,6 +140,9 @@ bool ta_init(const void *base, const void *limit, const size_t heap_blocks, cons
134140
}
135141

136142
bool ta_free(void *free) {
143+
if (free == NULL) {
144+
return false;
145+
}
137146
Block *block = heap->used;
138147
Block *prev = NULL;
139148
while (block != NULL) {
@@ -159,7 +168,11 @@ static Block *alloc_block(size_t num) {
159168
Block *ptr = heap->free;
160169
Block *prev = NULL;
161170
size_t top = heap->top;
171+
size_t orig = num;
162172
num = (num + heap_alignment - 1) & -heap_alignment;
173+
if (num < orig) {
174+
return NULL; // overflow
175+
}
163176
while (ptr != NULL) {
164177
const int is_top = ((size_t)ptr->addr + ptr->size >= top) && ((size_t)ptr->addr + num <= (size_t)heap_limit);
165178
if (is_top || ptr->size >= num) {
@@ -218,9 +231,15 @@ void *ta_alloc(size_t num) {
218231
if (block != NULL) {
219232
return block->addr;
220233
}
234+
#ifdef TA_USE_STDLIB
235+
errno = ENOMEM;
236+
#endif
221237
return NULL;
222238
}
223239

240+
#ifdef TA_USE_STDLIB
241+
#define memclear(ptr, num) memset((ptr), 0, (num))
242+
#else
224243
static void memclear(void *ptr, size_t num) {
225244
size_t *ptrw = (size_t *)ptr;
226245
size_t numw = (num & -sizeof(size_t)) / sizeof(size_t);
@@ -233,14 +252,23 @@ static void memclear(void *ptr, size_t num) {
233252
*ptrb++ = 0;
234253
}
235254
}
255+
#endif
236256

237257
void *ta_calloc(size_t num, size_t size) {
258+
size_t orig = num;
238259
num *= size;
260+
if (size != 0 && num / size != orig) {
261+
goto overflow;
262+
}
239263
Block *block = alloc_block(num);
240264
if (block != NULL) {
241-
memclear(block->addr, num);
265+
memclear(block->addr, block->size);
242266
return block->addr;
243267
}
268+
overflow:
269+
#ifdef TA_USE_STDLIB
270+
errno = ENOMEM;
271+
#endif
244272
return NULL;
245273
}
246274

@@ -268,3 +296,41 @@ size_t ta_num_fresh() {
268296
bool ta_check() {
269297
return heap_max_blocks == ta_num_free() + ta_num_used() + ta_num_fresh();
270298
}
299+
300+
size_t ta_getsize(void *ptr) {
301+
if (ptr == NULL) {
302+
return 0;
303+
}
304+
Block *block = heap->used;
305+
while (block != NULL) {
306+
if (ptr == block->addr) {
307+
return block->size;
308+
}
309+
block = block->next;
310+
}
311+
return 0;
312+
}
313+
314+
/* requires memcpy() */
315+
#ifdef TA_USE_STDLIB
316+
void *ta_realloc(void *ptr, size_t num) {
317+
if (ptr == NULL) {
318+
return ta_alloc(num);
319+
} else if (num == 0) {
320+
ta_free(ptr);
321+
return NULL;
322+
}
323+
size_t size = ta_getsize(ptr);
324+
Block *block = alloc_block(num);
325+
if (block != NULL) {
326+
if (size > num) {
327+
size = num;
328+
}
329+
memcpy(block->addr, ptr, size);
330+
ta_free(ptr);
331+
return block->addr;
332+
}
333+
errno = ENOMEM;
334+
return NULL;
335+
}
336+
#endif

tinyalloc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ bool ta_init(const void *base, const void *limit, const size_t heap_blocks, cons
99
void *ta_alloc(size_t num);
1010
void *ta_calloc(size_t num, size_t size);
1111
bool ta_free(void *ptr);
12+
size_t ta_getsize(void *ptr);
13+
14+
/* requires memcpy() */
15+
#ifdef TA_USE_STDLIB
16+
void *ta_realloc(void *ptr, size_t num);
17+
#endif
1218

1319
size_t ta_num_free();
1420
size_t ta_num_used();

0 commit comments

Comments
 (0)