From dcfd4c01ffa2a0c7469b8d20608c0e0daa35bd51 Mon Sep 17 00:00:00 2001 From: Imbus <> Date: Tue, 9 Sep 2025 11:00:25 +0200 Subject: [PATCH] More rigorous testing and helpful comments --- freelist/main.c | 83 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 20 deletions(-) diff --git a/freelist/main.c b/freelist/main.c index 79a39dd..ffb2068 100644 --- a/freelist/main.c +++ b/freelist/main.c @@ -18,20 +18,42 @@ void printvec(const Vec3 *v) { printf("Vec3: (%d, %d, %d)\n", v->x, v->y, v->z); } +/* For testing crc poly 0x04C11DB7 */ +uint32_t crc32(const uint8_t *data, size_t length); + #define BUFFER_SIZE (128) int main() { - FreeList fl; - const char *mem = malloc(BUFFER_SIZE); - memset((void *)mem, 0, BUFFER_SIZE); + FreeList fl; + + /* Here we split our malloc'ed memory into three parts, we pass one of + * them to our freelist, and keep the other two (head/tail) to check for + * overwrites: + * + * | Headblock | Freelist block | Tailblock | + * | 1x | 2x | 1x | + */ + void *headblock = malloc(BUFFER_SIZE * 2); + void *tailblock = headblock + (BUFFER_SIZE + BUFFER_SIZE / 2); + void *mem = headblock + (BUFFER_SIZE / 2); + + /* Set these buffers to something known and randomize the buffer we give to the freelist */ + memset(mem, arc4random(), BUFFER_SIZE); + memset(headblock, 0xAB, BUFFER_SIZE / 2); + memset(tailblock, 0xF0, BUFFER_SIZE / 2); + + /* Store these for reference at the end of the testing */ + const uint32_t tail_crc = crc32(tailblock, BUFFER_SIZE / 2); + const uint32_t head_crc = crc32(headblock, BUFFER_SIZE / 2); + + /* Display a nice hexdump so you can see the layout */ + hexdump(headblock, BUFFER_SIZE * 2); if (!fl_init(&fl, (uintptr_t)mem, BUFFER_SIZE, sizeof(Vec3))) { - printf("Allocation error\n"); + printf("Freelist failed to initialize!\n"); exit(EXIT_FAILURE); } - hexdump(mem, BUFFER_SIZE); - const size_t cap = fl_capacity(&fl); printf("Item size: %lu\n", sizeof(Vec3)); @@ -42,23 +64,17 @@ int main() { printf("Space utilization external: %.2f%%\n", 100.0 * ((float)fl.size * cap) / BUFFER_SIZE); assert(fl_available(&fl) == cap); - - if (!fl_check(&fl)) - printf("Check failed!\n"); - - printf("Check: %zu\n", fl_check(&fl)); + assert(fl_check(&fl) == cap); Vec3 *a = fl_alloc(&fl); Vec3 *b = fl_alloc(&fl); Vec3 *c = fl_alloc(&fl); - hexdump(mem, BUFFER_SIZE); + memset(a, 0xCA, sizeof(Vec3)); + memset(b, 0xCB, sizeof(Vec3)); + memset(c, 0xCC, sizeof(Vec3)); - memset(a, 0x23, sizeof(Vec3)); - memset(b, 0x24, sizeof(Vec3)); - memset(c, 0x25, sizeof(Vec3)); - - *a = vec3_new(12, 13, 435); + *a = vec3_new(0xAAAA, 0xAAAA, 0xAAAA); *b = vec3_new(192, 199, 435); *c = vec3_new(432, 11, 435); @@ -91,12 +107,10 @@ int main() { /* Write some data to the last element to catch out of bounds writes */ size_t last_elem = fl_capacity(&fl) - 1; - *(Vec3 *)ptr_buf[last_elem] = *a; + memset((void *)ptr_buf[last_elem], 0x42, sizeof(Vec3)); assert(0 == fl_available(&fl)); assert(fl_allocated(&fl) == fl_capacity(&fl)); - - printf("Check: %zu\n", fl_check(&fl)); assert(fl_check(&fl) == 0); /* Return it all */ @@ -104,10 +118,39 @@ int main() { fl_free(&fl, (void *)ptr_buf[i]); } + free(ptr_buf); + + /* All slots are free here */ assert(cap == fl_available(&fl)); assert(fl_allocated(&fl) == 0); assert(fl_check(&fl) == cap); + /* Check so our head and tail blocks are intact */ + assert(crc32(headblock, BUFFER_SIZE / 2) == head_crc); + assert(crc32(tailblock, BUFFER_SIZE / 2) == tail_crc); + + /* Hexdump the heap, free the block and declare victory */ + hexdump(headblock, BUFFER_SIZE * 2); + free(headblock); printf("All tests passed!\n"); return 0; } + +uint32_t crc32(const uint8_t *data, size_t length) { + uint32_t crc = 0xFFFFFFFF; + uint32_t poly = 0x04C11DB7; + + for (size_t i = 0; i < length; i++) { + crc ^= ((uint32_t)data[i]) << 24; + + for (int j = 0; j < 8; j++) { + if (crc & 0x80000000) { + crc = (crc << 1) ^ poly; + } else { + crc <<= 1; + } + } + } + + return crc ^ 0xFFFFFFFF; +}