Your bump allocator suffers from integer overflows turned into buffer overflows when the requested allocation is big enough:
if (a->cursor + size > a->limit) return NULL; // out of memory
I'd rewrite it like this: if (size > a->limit - a->cursor) return NULL; // out of memoryYour test is backwards. I would write it like this:
if (size > a->limit - a->cursor) return NULL;
I used the compiler's __builtin_add_overflow in order to deal with that issue in my memory allocator. At this point I'm probably on track to replace every arithmetic operator in the entire codebase with those things.