avr-libc
avr-libc copied to clipboard
[bug #40535] realloc(xxx, 0) doesn't free
Sun 10 Nov 2013 12:11:09 PM CET
realloc(xxx, 0) is supposed to free the given memory block if xxx is not NULL, If xxx is NULL, realloc() is supposed to work like malloc().
So I suggest to modify
in that way to add after
/* Trivial case, required by C standard. */ if (ptr == 0) return malloc(len);
the lines
/* Another trivial case, required by C standard. */ if (len == 0) { free(ptr); return NULL; }
because in this case
- realloc(NULL, 0) returns the same as malloc(0)- realloc(anythingelse, 0) does free(anythingelse).This behaviour is required by the standard.
This issue was migrated from https://savannah.nongnu.org/bugs/?40535
Thomas R.
I hope the project still lives on that given SVN and I don't suggest something that has already been fixed.
If this doesn't get fixed, the code in realloc() ignores the fact that fp1 == fp2 and there happen potentially nasty things with the freelist.
Joerg Wunsch <joerg_wunsch> Sun 10 Nov 2013 01:55:45 PM CET
realloc(xxx, 0) is supposed to free the given memory block if xxx is not NULL
Can you point me to a wording in the standard that would require this? I can't seem to find something to that effect.
The rationale allows this to be one possible implementation, but it's not mandated. Our implementation simply deallocates as much as possible, and the returned object pointer is consistent with a pointer to an object resulting out of malloc(0).
I tend to dismiss the request since it bears the risk of introducing new bugs, of course unless someone can prove the existing implementation violates the C standard.
Joerg Wunsch <joerg_wunsch> Sun 10 Nov 2013 02:03:25 PM CET
If this doesn't get fixed, the code in realloc() ignores the fact that fp1 == fp2 and there happen potentially nasty things with the freelist.
Could you provide a testcase for this? Ideall, something that would fit into tests/simulate/stdlib/realloc-*.c.
Thomas R.
I stand corrected. I saw in the Linux man page for realloc(3) that calling it with length == 0 would require to free() and thought this was actually required by the standard. But I don't find that in the standard, so probably I was wrong there.
About my claim concerning destroyed free list, I stand corrected as well. The free list is not destroyed immediately, but:
- cp1 and fp1 point to ptr-sizeof(size_t)
- cp and fp2 point to ptr + len, which is ptr if len == 0
- This makes fp1->nx and fp2->sz sharing the same address (ptr) [*]
- the fp2 part is added as a new entry to the free list, leaving the old memory block having a length field of 0 and nothing else, even no space for a ->nx pointer.
This does not hurt until I call free(ptr), ptr being the value just returned from realloc(). There the fact [*] above makes it impossible to add the now being freed part, which is uncapable to hold a nx pointer, to the free list, as the said fp2->sz is now tampered as well.No matter if that part of memory is still free or allocated in the meanwhile, this leads to trouble sooner or later.
This fact makes this bug a duplicate of bug #32702, which AFAICS already contains a test case and which I would consider as rather severe and important in turn.
Additionally, I'd like to write a test case proving that the bug is destructive if realloc() is called with a new length of < sizeof((struct __freelist).nx) if that is necessary. But that may take some days, as I first would have to wrap my head around making the test cases work in my build environment. Maybe I get the opportunity in the next days to do so.
Again, sorry for the noise made by contradicting myself, and for sounding quite vague, but nevertheless I hope that I could contribute and/or help concerning that bug #32702.