2 ms·
The issue is that value is only checked in the context of a use-after-free error though, which the compiler assumes never happens, so it doesn't actually matter
by DSMan195276 5y ago
The issue is that value is only checked in the context of a use-after-free error though, which the compiler assumes never happens, so it doesn't actually matter to the optimizer. The code I wrote will optimize the same way even if I add a random pointer assignment or read elsewhere (any of which could technically trigger a use-after-free), because the compiler is allowed to assume that because I'm passing that pointer to `free()` I'm never going to use it again.
To show this even more, if you add an extra printf to print the value of p after the `free()` (so add a literal use-after-free to check the 'magic' value) the 30 assignment is still gone. It prints zero for me because free() clears that memory, but the assembly does not include the 30 assignment even though I'm clearly reading the value it assigned after the `free()` statement, which is exactly the behavior you're attempting to catch. If `free()` didn't touch the value I'd still see 20.
With a little finessing I got my code to print 20 both times (the larger struct gets malloc() to leave the magic value alone) even with the 30 assignment still in the code:
struct foo {
char bar[35];
int p;
};
int main()
{
struct foo *p = malloc(sizeof(*p));
*(volatile int *)(&p->p) = 20;
printf("p=%d\n", p->p);
p->p = 30;
free(p);
printf("p=%d\n", p->p); /* Prints 20 for me, the 30 assignment is optimized out completely */
return 0;
}