While I was doing my assignment I came across an issue. I know that double freeing cause undefined behavior.
When a program calls free() twice with the same argument, the program's memory management data structures become corrupted. This corruption can cause the program to crash or, in some circumstances, cause two later calls to malloc() to return the same pointer. If malloc() returns the same value twice and the program later gives the attacker control over the data that is written into this doubly-allocated memory, the program becomes vulnerable to a buffer overflow attack.
CWE-415: Double Free
However, while fuzzing I encountered double NULL(set NULL twice(one after another) for one variable) where pointer was NULL(ed) twice.
Is that same with double freeing and cause undefined behaviour?
e.g.
int *p;
p = (int*)malloc(10*sizeof(int));
p = NULL;
p = NULL; (**seconds time)**
I'm not quite sure what you're asking about, but:
if you try to free() the same memory block twice in a row:
void* ptr = malloc(120);
free(ptr);
free(ptr);
then the second call to free() will probably corrupt the heap;
however, if you set your pointer variable to NULL after freeing the pointed block:
void* ptr = malloc(120);
free(ptr);
ptr = NULL;
// ....do some other stuff
// (but no assignment to ptr!)
free(ptr);
ptr = NULL;
then the second call to free() passes a NULL pointer to it, and free() returns with no harm.
Setting ptr to NULL does not free the allocated memory. This would work e.g. in Java, where the virtual machine tracks all references to objects and deletes those no longer used. In that context the first ptr = null; would make a pointed object eligible for deleting (provided no other references to it exist), and another ptr = null; would not change anything.
In C you must 'manually' release memory you allocated and that is quite separate from nullifying any pointer variables.
If you do
int *p;
p = (int*)malloc(10*sizeof(int));
p = NULL;
p = NULL;
then you: declare a p variable; allocate a block of memory and store its address in the p variable; overwrite the stored address with a NULL pointer (thus effectively you loose access to the allocated memory block); and overwrite it once again with the same NULL value.
That does not affect the allocated block. It remains allocated till the end of your program execution, but without the pointer value returned from malloc() you can't use it or even free() it. That's what we call a memory leak.
A pointer can be "nulled" twice, because its just assigning a value to it. The memory however is still allocated. Setting the pointer to null won't change that. This is why you can do this as often as you like.
With free()-ing the pointer however, you're deallocating the memory. This means is could be used for other variables and such.
Once the memory was deallocated, you can't deallocate it a second time, this is why it causes undefined behaviour.
Have a look at this question for reference.
NULL is a macro that most of the times stands for 0. So all you do is, assign 0 twice to a variable. So pretty defined behaviour...
Related
whenever I read dangling pointers article. I can not anticipate the potential risk here.
What is the issue in below code if I do not initialize the pointer, or I do not assign ptr to NULL after deal locating malloc? Why it becomes dangling, what is the risk here?
int main()
{
int *ptr; //what is risk here?
ptr = (int *)malloc(sizeof(int));
// After below free call, ptr becomes a
// dangling pointer
free(ptr);
//ptr = NULL; //what is risk here if i do not assign NULL?
}
There is only a dangling pointer risk if you use a pointer when the data it points to is no longer valid. That is not the case in your code snippet provided.
If you do use it while the data it points to is invalid (uninitialised before the malloc or dangling after the free), all bets are off, that's undefined behaviour (UB).
It's also UB if you use the NULL that may be returned if your malloc failed, you should always check for that. And, because of that, setting it to NULL after the memory it points to ceases to be valid will not help you at all. It's just as much UB to dereference NULL as it is to dereference memory that's been freed.
You can make your code a lot safer with something like:
int main(void) {
int *ptr = malloc(sizeof(int));
if (ptr == NULL) {
puts("Could not allocate");
return 1;
}
// safe to use pointer here.
free(ptr);
// but not here.
}
The risk is not in the code shown, the risk is in the code after maintenance, modification and reuse. Or in "cargo-cult" copying of the anti-pattern. If for example you added a great deal of code between the initialised ptr declaration and the malloc(), it may no longer be clear that the pointer is not yet valid.
Dereferencing a null pointer "by accident" will normally be trapped as a run-time error, so likely to be detected during testing and development and reported at the point of error. Dereferencing a pointer that is a valid address but say refers to a block returned to the heap for re-use may have no immediate observable impact, but may later cause unrelated code to fail, possibly after deployment and in unpredictable ways - those bugs are very difficult to track down.
Dereferencing a pointer that simply has not been initialised, will have undefined behaviour, it may appear to work, it may trigger an exception, it may cause the code to appear to fail at an unrelated location in the code - again such bugs are hard to track down unless you were lucky enough for it to fail immediately - if it happened to be NULL or an invalid address triggering an exception for example.
Besides that, there are no advantages to the "unsafe" code:
int *ptr; //what is risk here?
ptr = (int *)malloc(sizeof(int));
over both safer and simpler code thus:
int* ptr = malloc( sizeof(*ptr) ) ;
Note other improvements in this:
do not cast a void-pointer to the destination type,
use the sizeof the object pointed to (or a multiple thereof) rather than an explicit type.
Remember in modern C, is is no longer necessary to declare all variables at the start of a brace-block ({...}) - though you will still see that anti-pattern too - so there are few excuses for not initialising a pointer with a useful value on instantiation.
int main()
{
int *ptr; //what is risk here?
ptr = (int *)malloc(sizeof(int));
Here you have 2 risks. The first one is that in real project between these 2 lines of code it could be a lot of another code. And there is a chance that you (or somebody else who maintains this code) will try to dereference this pointer before it's initialised.
The second one is that the return value of malloc is not checked, so in case if malloc failed, you will not know that it failed.
free(ptr);
//ptr = NULL; //what is risk here if i do not assign NULL?
When you make free() you don't really "free" the memory (you don't set all bits in allocated chunk of memory to '0') you just mark this memory as "it could be allocated again in future allocations). But your pointer is still points to this chunk of memory. So after some period of time this chunk of memory could be used for another allocation. Some new data will be stored to this chunk (data will be overwritten). And your pointer will point to the memory that stores not relevant data. And you (or worth - somebody else who maintains your project) could use this pointer without knowing that he points to non-relevant data.
I am new in C programming language so can you tell me if this is correct way to do.
for example:
program points on buffer and i use that pointer as parameter in free() function. So, what problems can this function cause ?
You should call free only on pointers which have been assigned memory returned by malloc, calloc, or realloc.
char* ptr = malloc(10);
// use memory pointed by ptr
// e.g., strcpy(ptr,"hello");
free(ptr); // free memory pointed by ptr when you don't need it anymore
Things to keep in mind:
Never free memory twice. This can happen for example if you call free on ptr twice and value of ptr wasn't changed since first call to free. Or you have two (or more) different pointers pointing to same memory: if you call free on one, you are not allowed to call free on other pointers now too.
When you free a pointer you are not even allowed to read its value; e.g., if (ptr) not allowed after freeing unless you initialize ptr to a new value
You should not dereference freed pointer
Passing null pointer to free is fine, no operation is performed.
Think that the computer has a whole bunch of memory not (yet) used by your program. Now you need some more memory and you ask your computer to give you some more (for example, a large buffer). Once you are done with it, you want to return it to the computer.
This memory is called the heap. You ask for memory by calling malloc() and you return it by calling free();
char *buffer;
buffer = malloc(512); // ask for 512 bytes of memory
if (buffer==NULL) return -1; // if no more memory available
...
free(buffer); // return the memory again
free() function is used to deallocate memory used by one program and move it back to available memory area so that other operating system processes can use that memory location. Also free function takes any type of pointer that points to that memory location.
For example:
int a = 10; // suppose 2 byte is allocated ie location 1000 and 1001
Now this 2 byte of memory belongs to specific problem; hence OS will not give this memory location to another process (memory is now allocated memory not available memory)
int *ptr =&a;
/*ptr is pointer variable pointing to 1000
as it is int pointer therefore ptr++ will move pointer to 1002*/
Now if we do free(ptr), it will check the pointer type and depending on type free function deallocate memory in this case 2 bytes starting from 1000.
Now interesting point is your data will be there until OS allocates this memory to some other process and that process overwrites it.
Also ptr is pointing to 1000 even after free() function but that memory location does not belong to our program hence ptr pointer has given new name DANGLING POINTER.
*ptr may or may not give the same value therefore it is better to make ptr =null.
From the man page of free() function:
The free() function frees the memory space pointed to by a pointer ptr which must have been returned by a pre‐
vious call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called
before, undefined behavior occurs. If ptr is NULL, no operation is performed.
You have to use the free() function when you are allocating the memory dynamically.
If you are using that as a static variable then it may lead to unintended behavior.
char *c=malloc(100);//allocating the 100 bytes of memory for a pointer variable c.
Here after usage of that varaible you can free that allocated memory,
free(c);
If you are declared a variable like this,
char c= malloc(100);// It is illegeal. And c will have a memory in stack.
If you free this variable,
free(c);//it will lead to system crash. Because your freeing the memory which is in stack memory.
gcc (GCC) 4.7.0
c89
Hello,
I am wondering if I am thinking correctly here. When I allocate memory using malloc. malloc will return a pointer to a size in memory.
So before I allocate my memory all pointers will have the value NULL.
Using this code snippet:
struct address *db_row = NULL;
db_row = malloc(sizeof(struct address));
db_row->name = malloc(sizeof(char) * 10);
db_row->email = malloc(sizeof(char) *10);
free(db_row->name);
free(db_row->email);
free(db_row);
I have done this in the gdb debugger for db_row before allocating memory:
(gdb) p db_row
$20 = (struct address *) 0x0
(gdb) p *db_row
Cannot access memory at address 0x0
Which is correct, as no memory address has been allocated.
After I allocate memory I get the following when I do the same:
(gdb) p db_row
$25 = (struct address *) 0x602310
(gdb) p *db_row
$26 = {id = 0, set = 0, name = 0x0, email = 0x0}
However, after I have free the memory I still get the same memory address, should it not be NULL as in the first case before allocating any memory?
After freeing the memory:
(gdb) p db_row
$28 = (struct address *) 0x602310
(gdb) p *db_row
$27 = {id = 6300480, set = 0, name = 0x602330 "", email = 0x602350 " #`"}
As you can see its still pointing to the same memory location, is this correct?
Finally, I added this at the end to see if I could do a double free:
if(db_row != NULL) {
free(db_row);
}
if(db_row != NULL) {
free(db_row);
}
I get a stack dump on the second call to free. But as a safety measure should you always check to make sure you are not trying to do a double free?
It it worth setting the pointers to NULL after free them?
db_row = NULL;
Many thanks for any suggestions,
But as a safety measure should you always check to make sure you are not trying to free a NULL pointer?
Calling free() with a NULL pointer is safe and nothing occurs. Calling free() does not NULL the pointer, you may do this explicitly. NULLing a pointer after calling free() would prevent the double free on the same pointer variable:
/* Assuming 'db_row' is referring to a valid address
at this stage the following code will not result
in a double free.*/
free(db_row);
db_row = NULL;
free(db_row);
If another pointer variable is pointing to the same address and is passed to free() then a double free still occurs.
Just because a pointer is not-NULL does not guarantee that it points to a valid address. It is the programmer's responsibility to ensure double free()s do not occur. NULLing pointer variables after a call to free() helps but does not provide a guarantee as multiple pointer variables can be pointing at the same address.
But as a safety measure should you always check to make sure you are not trying to do a double free?
There is no way to query a pointer variable to determine if the memory at the address that it holds has already been free()d. A pointer variable holds an address, nothing more.
It is good practice to set a pointer to null after freeing it unless you are at the end of the scope of the variable; and yes it is normal that free does not do that.
If the pointer is null, calling free on it is safe, and any access to it will generate a core dump, which is much easier to debug than memory corruption or double free that could occur if you use a freed pointer not set to null.
After I have free the memory I still get the same memory address, should it not be NULL as in the first case before allocating any memory?
Because free() only releases the memory that was allocated to you. It dos not set the pointer to NULL.
But as a safety measure should you always check to make sure you are not trying to free a NULL pointer?
If pointer passed to free() is a null pointer, then no action occurs(C99 section 7.20.3.2).
It it worth setting the pointers to NULL after free them?
There is absolutely no merit in doing so, more often it would end up hiding your problems which will raise their ugly head in some or other form.
It is a defensive and dubious style of programming to avoid dangling pointers or double free problems, wherein you try to safeguard yourself against free() getting called on the same pointer.In reality more often or not the double free problem occurs when you different pointers to the same memory and these different pointers are passed to free().
The practice of making the pointer NULL does nothing in the second and more common bug scenario. All of these situations can only be avoided by writing programs by putting in some good thought and periodic code reviews.
To try to be clear here, I'm going to quote from the man page of malloc:
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.
So, to recap:
Free takes a pointer returned by a memory allocation function (NULL or valid)
If it's NULL, nothing happens
If it's a valid pointer it frees the memory
You'll note here it says nothing about changing the address that ptr is pointing to. That's on you to do. So it's very safe to do:
int *p = malloc(sizeof(int));
*p = 5;
printf("p=%d\n",*p);
free(p);
p = NULL;
Now you can call free() all day long on your pointer p and you're OK. If you're concerned about having errors with double free() calls, on recent versions of Linux libc (later than 5.4.23) and GNU libc (2.x) there is a saftely mechanism in place called MALLOC_CHECK_
Instead of getting a stack crash you'll see a message such as:
*** glibc detected *** ./a.out: free(): invalid pointer: 0x0804b008 ***
You can use it in the following ways:
export MALLOC_CHECK_=0 to turn off malloc check and (possibly) let your program crash
export MALLOC_CHECK_=1 you'll get the above warning message
export MALLOC_CHECK_=2 Will call abort(1) and give you a back trace of your code
export MALLOC_CHECK_=3 is just option 1|2 together
Tried the following code :
#include<stdio.h>
int main()
{
int *p,*q;
p = (int *)malloc(sizeof(int));
*p =10;
q = p;
printf("%u \n",p);
printf("%u \n",q);
free(p);
printf("%u \n",p);
return 0;
}
The output got is as follows :
[root#lnxdesk Tazim]# ./a.out
154804232
154804232
154804232
Why is that address inside p is still printed even if I have done free(p);?
What has free(p) done then?
I want to understand the concept of free/malloc clearly. Any help will be valuable.
free() only frees the memory on the heap. It does not change the value of your pointer. If you tried to print the memory pointed by your pointer, you'll probably get some kind of garbage.
Also, when you called free, you gave it the pointer, not the address to your pointer, so free can't change your pointer...
That's undefined behavior - once you've freed the pointer the address stored becomes invalid and you can't do anything with it - not only you can't dereference it, but you can't even printf() the pointer value.
You are printing the pointers, i.e. the address of the memory zones allocated for you ints. Freeing a memory zone with free does not set the pointer's address to 0x00 as I think you expect.
It just tells the OS that the memory zone is available again for future re-use.
If you were printing *p after free(p), you would have problems.
malloc() and its ilk reserve space in a memory storage area called the "heap" and return a pointer to that reserved area. So in your sample above p is given a pointer to, probably, a four-byte memory region that has been reserved for its use (whose address happens to be 154804232 this time around). When you do *p = 10 you are now placing the integer value 10 into the memory pointed to. When you do q = p you're now making q point to the same chunk of reserved heap memory.
free() and its ilk just unreserve the memory. When you call free() you're saying "I'm not going to use this memory anymore". All free() does is tell the memory management system that the block of memory is now available for use once again. It emphatically does not change your pointer. It just signals that the block of memory is available. After that it is up to you to ensure that you do not use that pointer again.
If you do use that pointer again it may work fine. Once. Or twice. Or a thousand times. It'll work fine, basically, until you use it after someone else claims that memory block you've said is free and does something with it. When that transpires, Bad Things Happen<tm>. Please don't make bad things happen.
Remember : a pointer is nothing but an address. Before, after your malloc, or free, it'll give you the same result. The only thing that malloc() does is reserve space at this address. The only thing that free does is release it (most probably, mark this address as usable to store other things, "cleaning" would be time consuming).
This is why putting your pointer to NULL after a free is a good idea ; because you can be sure if the pointer is connected to something or not.
free does not reassign the pointer to point to something else. In fact, the C standard
does not mention anything be done with the pointer. This is all it says in the description:
The free function causes the space
pointed to by ptr to be deallocated,
that is, made available for further
allocation. If ptr is a null pointer,
no action occurs. Otherwise, if the
argument does not match a pointer
earlier returned by the calloc,
malloc, or realloc function, or if the
space has been deallocated by a call
to free or realloc, the behavior is
undefined
Could somebody tell me the difference between:
int *p;
p=(int*)malloc(10*sizeof(int));
free(p);
or
int *p;
p=(int*)malloc(10*sizeof(int));
p=NULL;
free will deallocate the memory that p points to - simply assigning it to NULL will not (and thus you will have a memory leak).
It is worth mentioning that it is good practice to assign your pointer to NULL AFTER the call to free, as this will prevent you from accidentally trying to access the freed memory (which is still possible, but absolutely should not be done).
There is no garbage collection in C, so if you don't explicitly free a chunk of memory, it will never get freed, even if there are no references to it. Maybe you come from a background in garbage collected languages, so it might be hard to change your way of thought, but it's always important to remember to "manually" free all resources in low-level languages like C.
Hope this helps
Cheers
p is pointer (to a block allocated dynamically in memory ["on the Heap"])
This means that p is a variable which contains the address in memory of a particular block (or some particular size, in the example a block big enough to hold 10 integers).
free(p); instructs the memory management logic (of the C Runtime) that the memory previously occupied by the block which p points to can be reused.
p = NULL; sets the value of p to NULL (the address it formerly contained is lost) but the block in memory it pointed too is still considered in use.
There can be some confusion because in languages such as Java, C#, Python etc. merely assigning the variable to NULL (or to another address for that matter), will automatically free the underlying memory (assuming no other references to this address exist in other live variables).
This is not the case in C or C++, leading to errors like the following:
free(p);
// possibly some some code etc.
// later:
p[6] = 'a'; // <<--- Ouch we're modifying whatever new variable is there !!!
or
// didn't call free(p)
p = NULL;
// now the memory allocated for p is held in memory even though it
// is not going to be used (assuming no copies of p or of pointers to part
// of that block were made.
The latter case is only wasteful of resources, the former can lead to hard to find bugs.
That's why a typical C idiom is:
free(p);
p = NULL;
Not calling free and directly assigning to NULL will lead to a memory leak as explained by others. You can refer to this link to get clear details about memory leaks and other memory related problems.
The better way is to first free the memory and then set it to NULL:
free(p);
p = NULL;
Freeing the allocated memory deallocates it and allows that memory to be used elsewhere while the pointer to where the memory was allocated is preserved.
Setting a pointer to the allocated memory to NULL does not deallocate it.
If you are using an implementation that uses a heap-based malloc, debug something that allocates, uses and frees memory, and do the same to something that allocates, uses, and sets the pointer to the memory to NULL.
Memory management is implementation-dependent (see http://en.wikipedia.org/wiki/Malloc#Implementations).
1.
int *p;
p= (int * ) malloc(10*sizeof(int));
free(p);
the memory is released back to the heap. but the pointer still pointing to the freed memory location. Thus if its further used , would lead to a memory corruption.
thus correct thing to do is resetting the pointer to NULL explicitly to avoid further usage of that pointer .
its not advisable to type cast the return pointer in C
2.
int *p;
p=(int * )malloc(10*sizeof(int));
p=NULL;
This would result in a memory leak : as the allocated memory is not freed here. you are just reset the pointer to NULL.
p=NULL does not deallocate the memory. If you don't need to use the memory pointed by p anymore you should use free() otherwise there will be memory leak. You should also set p=NULL after calling free() to avoid erroneously accessing that memory again in the future.