avr-libc – Realloc bug

A few months ago I proposed a refactor for the Arduino RepRap firmware. I was quick to code it up and build test cases on the desktop, then ported to the Arduino… Where it failed miserably. There the code languished as I spent time on it here and there. I attempted getting SimulAVR working, but it doesn’t support the Arduino chipsets (thought about adding support). I tried AVR Studio in a bootcamp’d windows install, but it kept hanging when debugging this problem. As a last resort, I ported the avr-libc memory apis to the initial desktop refactor, and was able to see the problem clear as day. I spent some time reducing the repro to the smallest form:

void testMalloc()
{
    size_t* array = (size_t*)malloc(4 * sizeof(size_t));
    free(array);
    array = NULL;

    array = (size_t*)realloc(array, sizeof(size_t));
    array = (size_t*)realloc(array, 2 * sizeof(size_t));
    array = (size_t*)realloc(array, 3 * sizeof(size_t));
    realloc(array, 4 * sizeof(size_t));
}

There is a bug in the free list manager in Realloc, specifically when growing a buffer into the next free entry. I was convinced I had a bug in a fairly large codebase, and whittled it down to this reproduction. I’m now playing with a couple of fixes, but need to figure out how to get a ‘blessed’ fix into lib-avr.

Stepping through the malloc into the free results in:

00000010 00000000 00000000 00000000
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000

Over the first realloc:

00000008 00000000 00000000 00000004
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000

Over the third:

0000000c 00000000 00000000 00000004
00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000

And finally:

00000010 00000000 00000000 00000004
00000000 FFFFFFFC 00000000 00000000
00000000 00000000 00000000 00000000

At this point the free block pointer (__flp) points to the second line, with a size of 0xfffffffc. The next allocation fails.