53

As the title suggests I am new to C and have a mid-term coming up shortly. I am revising from past papers currently and a recurring theme is the double free problem. I understand that it is the process of calling free() on the same memory location twice, but I have a couple of questions that I'm not 100% sure how to answer:

Question 1: What is the result of a double free in C, and why is it such a problem?

This will cause a double free:

char* ptr = malloc(sizeof(char));

*ptr = 'a';
free(ptr);
free(ptr);

My response to this would be that it would return a 0x0 memory address and cause a system instability/crash. Also if I remember correctly, a double free can actually call malloc twice which results in a buffer overflow thus leaving the system vulnerable.

What would be the best way to briefly sum up this question?

Question 2: Describe a situation in which it is particularly easy to introduce a double free in C?

I was thinking when passing pointers around you may accidentally free it in one function, and also free it again without realising?

Again, what is the "best" way to sum this up?

Matthias Braun
  • 32,039
  • 22
  • 142
  • 171
chris edwards
  • 1,332
  • 4
  • 13
  • 31
  • 14
    `"...would it return a 0x0 memory address..."` - what is this about? Would *what* return a 0x0 memory address? Function `free` does not return anything. – AnT stands with Russia Jan 11 '14 at 01:51
  • Double free bugs can sometimes be extremely serious security vulnerabilities - here is an example: https://awakened1712.github.io/hacking/hacking-whatsapp-gif-rce/ – Sachin Joseph Oct 03 '19 at 00:08

4 Answers4

65

A double free in C, technically speaking, leads to undefined behavior. This means that the program can behave completely arbitrarily and all bets are off about what happens. That's certainly a bad thing to have happen! In practice, double-freeing a block of memory will corrupt the state of the memory manager, which might cause existing blocks of memory to get corrupted or for future allocations to fail in bizarre ways (for example, the same memory getting handed out on two different successive calls of malloc).

Double frees can happen in all sorts of cases. A fairly common one is when multiple different objects all have pointers to one another and start getting cleaned up by calls to free. When this happens, if you aren't careful, you might free the same pointer multiple times when cleaning up the objects. There are lots of other cases as well, though.

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • I am finding a bunch of undefined behaviours in C so I expected something along those lines. I was going to suggest the possibility of a single/doubly linked list being very susceptible to the double free for that reason, thanks for your response. – chris edwards Jan 11 '14 at 01:57
  • What does free() do under the hood. To me it seems like the memory manager should say that pointer does not exist if you try to free it again and the CPU causes an interrupt. And the same thing with use after free vulnerabilities but that is not what happens. – Deoxal Sep 19 '22 at 17:53
  • 1
    @Deoxal Most memory managers work by periodically getting a huge block of memory from the OS and subdividing it in some way that allows small pieces of the large block to be given out when `malloc` is called. As a result, memory managers generally don’t return memory back to the OS when `free` is called, because other allocated memory might exist in the same page that the deallocated block comes from. – templatetypedef Sep 21 '22 at 16:38
  • I see, that makes sense but does the memory manager returna pointer's data if I ask for it immediately after freeing it? – Deoxal Sep 22 '22 at 02:57
  • @Deoxal It depends on the memory manager implementation. Some MMs will overwrite freed blocks with other data needed for internal bookkeeping. Others will clear things out for safety. Others do neither. – templatetypedef Sep 22 '22 at 04:51
14

Because free() will consolidate adjacent regions by managing the information stored in the tags before each region. It is something like managing the double linked list. So it would be dangerous if the buffer where ptr is pointing has been overwritten by an attack string, in which fake tags can be injected.

zero_yu
  • 493
  • 5
  • 15
7

This question has been well answered, but I add a late answer due to a "duplicate question" link, which asked "how to avoid it?"

One line is added to the example code posted.

char* ptr = malloc(sizeof(char));

*ptr = 'a';
free(ptr);
ptr = NULL;         // add this
free(ptr);

Function free does nothing with a NULL pointer.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
  • 11
    This is useful only in the trivial case where there is only one pointer to a piece of memory. In the more common situation where there are multiple pointers to the same memory it is much more complicated. – Sled Jan 24 '19 at 18:28
5

As per published C11 standard, calling free on already free memory location leads to undefined behaviour. It can lead to bizarre situations such as memory not getting allocated even when it's available, heap getting corrupt, same memory location getting allocated to different mallocs etc. Basically, it is undefined and can be anything.

ANSI C11 std can be found here. https://www.iso.org/obp/ui/#iso:std:iso-iec:9899:ed-3:v1:en

EDIT: changed NULL to already freed, based on comments. also, link now points to ISO/IEC 9899:2011(en)

ankurgupta7
  • 75
  • 1
  • 3
  • 3
    Where did you find this information? ("Calling free on NULL pointer leads to undefined behavior.") This is incorrect. – Filip J. Feb 24 '16 at 08:09
  • 3
    "Double free" and "free on NULL" are two separate issues. The former is undefined behavior but the latter is a harmless no-op. – jbm Apr 27 '16 at 12:09
  • 1
    Are you sure this is correct? The draft ISO standard I have explicitly says that calling `free` on a null pointer has no effect. – templatetypedef May 04 '16 at 01:14
  • i am sorry. my bad. meant doubly free'd. introduced few edits to the original answer. also @templatetypedef username checks out. – ankurgupta7 Feb 24 '17 at 07:40