Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Kernighan and Ritchie also correct this error by storing a reference to p->next  in q before freeing p.:

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
 
struct node {
  int value;
  struct node *next;
};
 
void free_list(struct node *head) {
  struct node *q;
  for (struct node *p = head; p != NULL; p = q) {
    q = p->next;
    free(p);
  }
}

...

In this noncompliant example, a diagnostic is required because realloc() may free c_str1 when it returns a null pointer, resulting in c_str1 being freed twice.  The WG14 committee's proposed response to Defect Report #400 makes it implementation-defined whether the old object is deallocated if size is zero and memory for the new object is not allocated, and the current implementation of realloc() in glibc will free c_str1 and return a null pointer for zero byte allocations.  Freeing a pointer twice can result in a potentially exploitable vulnerability commonly referred to as a "double-free exploit" [Seacord 2013].

Code Block
bgColor#FFCCCC
langc
#include <stdlib.h>
 
void f(char *c_str1, size_t size) {
  char *c_str2 = (char *)realloc(c_str1, size);
  if (c_str2 == NULL) {
    free(c_str1); // diagnostic required
    return;
  }
}

...

This compliant solution does not pass a size argument of zero to the realloc() function, eliminating the possibility of c_str1 being freed twice:

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
 
void f(char *c_str1, size_t size) {
  if (size != 0) {
    char *c_str2 = (char *)realloc(c_str1, size); 
    if (c_str2 == NULL) {
      free(c_str1); 
    }
  }
  return;
}

...

Freeing memory multiple times has similar consequences to accessing memory after it is freed.  FirstFirst, reading a pointer to deallocated memory is undefined behavior because the pointer value is indeterminate and might be a trap representation.   When reading a freed pointer doesn't cause a trap, the underlying data structures that manage the heap can become corrupted in a manner that can be exploited to execute arbitrary code.   These coding errors are referred to as "double-free vulnerabilities".

Programmers should be wary when freeing memory in a loop or conditional statement; if coded incorrectly, these constructs can lead to double-free vulnerabilities. It is also a common error to misuse the realloc() function in a manner that results in double-free vulnerabilities. (See MEM04-C. Beware of zero-length allocations.)

...