Sat 28 Feb 2009 02:06:08 AM UTC, original submission:
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
Over the first realloc:
00000008 00000000 00000000 00000004
- 00000000 00000000 00000000
- 00000000 00000000 00000000
Over the third:
0000000c 00000000 00000000 00000004
- 00000000 00000000 00000000
- 00000000 00000000 00000000
And finally:
00000010 00000000 00000000 00000004
- FFFFFFFC 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.
I've tracked it down to some free list tracking code in realloc.c, here's a patch for the fix, which I have verified.
Index: realloc.c
===================================================================
RCS file: /sources/avr-libc/avr-libc/libc/stdlib/realloc.c,v
retrieving revision 1.4
diff -r1.4 realloc.c
49c49
<
---
>
53c53
<
---
>
57c57
<
---
>
60c60
< /* Pointer wrapped across top of RAM, fail. */
---
> /* Pointer wrapped across top of RAM, fail. */
62,63c62,63
< fp2 = (struct __freelist *)cp;
<
---
> fp2 = (struct __freelist *)(cp - sizeof(size_t));
>
82c82
<
---
>
87c87
< incr = len - fp1->sz - sizeof(size_t);
---
> incr = len - fp1->sz;
89d88
< fp2 = (struct __freelist *)cp;
91,92c90,91
< fp3;
< ofp3 = fp3, fp3 = fp3->nx) {
---
> fp3;
> ofp3 = fp3, fp3 = fp3->nx) {
95,96c94
< if (incr <= fp3->sz &&
< incr > fp3->sz - sizeof(struct __freelist)) {
---
> if (incr <= fp3->sz + sizeof(size_t)) {
107c105
< fp2 = (struct __freelist *)cp;
---
> fp2 = (struct __freelist *)(cp - sizeof(size_t));
144c142
<
---
>
|