I am trying to track use-after-free errors in C. And my question is that, if I have the code like this:
A * ptrA = malloc(sizeof(A));
A * aliasA = ptrA;
// do something '
free(ptrA)
// some other code
B * ptrB = malloc(sizeof(B)); // assume this return same pointer as ptrA
//trying to use aliasA here
Just wondering if the use of aliasA is a UAF error? If it is, what is going wrong here?
To clear the question, I think it is better to add a small example:
int main(){
int *ptr = (int *)malloc(4);
*ptr = 5;
int *ptr2 = ptr;
printf("%d\n", *ptr);
free(ptr);
int *new_ptr = malloc(4);
*new_ptr = 66;
printf("%d\n", *ptr2);
return 0;
}
And the output is:
5
66
(I checked ptr
and new_ptr
in S2E: http://s2e.systems/ and these two pointers actually point to the same address. After freeing ptr, the same address is allocated to new_ptr.)
From the output above, it seems like the use of ptr2
gives the same output as new_ptr
.
When I wrote my solution to detect UAF error, I record the information of pointers. The pointers' values are stored as uint64_t
and a boolean type flag
is to declare whether the pointer is alive.
Therefore, I guess a problem occurs when the new_ptr
and ptr
point to same address because once malloc()
is called the flag
for new_ptr
will turn true
. After that, when I use ptr
, I can not detect this UAF error because this address is marked alive.
Thanks in advance!
The
aliasA
is UAF error, it may hold the same value asptrA
but it's not guaranteed and it's recommended to re-assign the freed pointer (both aliasA and ptrA) toNULL
to avoid dangling pointer.In your case, it's better to assign
NULL
after youfree
:If you don't dereference the pointer
aliasA
, it depends on the definition of "use after free" whether this constitutes "use after free". For example CWE-416 doesn't talk about just using the pointer value, but about dereferencing it, i.e. using the object that was freed.However, the C standard says that even using the pointer value has undefined behaviour (Appendix J.2):
This is because the value of the pointer becomes indeterminate:
Therefore the following code has undefined behaviour:
The comparison there is meaningless and the compiler is given the freedom to do whatever it pleases with its optimization, as
aliasA
doesn't need to contain a valid value any more. It is totally OK for a compiler to even to set a trap intoaliasA
which would cause your program to abort at theif
statement with a diagnostics message. Or it can be that these could seem to point to the same address even though they were given distinct addresses of memory, or vice versa.This is a UAF error.
In practice, it is very unlikely that the second
malloc()
call returns the same address asaliasA
, as the behavior is not guaranteed. You should not rely on it.You may ask: Can I compare them to make sure they have the same address? Well, no. Comparing may make some sense to you, but it is undefined behavior, because pointer equality comparison is valid only if the two pointers point to different elements in the same array. In this case the two allocated blocks surely aren't the same array, so comparison between those pointers isn't well-defined.
At last, you shouldn't rely on the address returned by
malloc()
. All you can do is use it within the amount of memory requested when calling.In practice, Thiru Shetty's answer is a good way to pursue.