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 function free takes a pointer as parameter and deallocates the memory region pointed to by that pointer. The memory region passed to free must be previously allocated with calloc , malloc or realloc . If the pointer is NULL , no action is taken.
But the memory allocation using malloc() is not de-allocated on its own. So, “free()” method is used to de-allocate the memory. But the free() method is not compulsory to use.
When you declare a pointer it will be allocated for it a memory location. That location can be reassigned. If you reassign it after having assigned it a value with a malloc() call and before to free() it, this is a memory leak. After free() you can reassign it and no leak will happen, do not forget to free() it again.
It means you're only supposed to call free on a pointer you obtained from malloc , realloc or calloc .
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):
The behavior is undefined in the following circumstances:
[...]
- The value of a pointer that refers to space deallocated by a call to the free or realloc function is used (7.22.3).
This is because the value of the pointer becomes indeterminate:
The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.
Therefore the following code has undefined behaviour:
A *ptrA = malloc(sizeof(A));
A *aliasA = ptrA;
free(ptrA);
A *ptrB = malloc(sizeof(A));
if (aliasA == ptrB) { // undefined behaviour, as it might be a trap
printf("We were given the same pointer");
}
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 into aliasA
which would cause your program to abort at the if
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.
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