The GNU libc manual page for mcheck says that the MCHECK_FREE status means "The block was already freed." That would imply to me that the block was freed (at least) once. This answer seems to imply the same in the code example. However, the Linux manpage says quite explicitly that MCHECK_FREE means "A block of memory was freed twice." I modified the code example from the above answer to make it slightly more descriptive:
#include <stdio.h>
#include <stdlib.h>
#include <mcheck.h>
void print_status(enum mcheck_status status)
{
switch(status)
{
case MCHECK_DISABLED:
printf("MCHECK_DISABLED\n");
break;
case MCHECK_OK:
printf("MCHECK_OK\n");
break;
case MCHECK_HEAD:
printf("MCHECK_HEAD\n");
break;
case MCHECK_TAIL:
printf("MCHECK_TAIL\n");
break;
case MCHECK_FREE:
printf("MCHECK_FREE\n");
break;
}
}
void no_op(enum mcheck_status status) {}
int main()
{
mcheck(&no_op);
void* f = malloc(4);
print_status(mprobe(f));
free(f);
print_status(mprobe(f));
return 0;
}
When I run this code I get this output:
MCHECK_OK
MCHECK_HEAD
This means I'm clearly getting MCHECK_HEAD as a response when checking a freed block. Is this behaviour reliable? Is it reasonable to expect that the header of a block will always be clobbered when it is freed? Are there different implementations of mcheck/mprobe that will return MCHECK_FREE instead?
I emailed a libc developer mailing list. I split my problem into 2 questions, each of which were responded to:
They are both correct, but written from slightly different perspectives.
If the block was previously free'd then you should return MCHECK_FREE.
However, if you can't detect that it was previously free'd because of corruption then you might only be able to return MCHECK_HEAD as the default results if the corruption has changed all co-located metadata about the state information.
Yes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With