You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 3 Next »

Accessing memory once it is freed corrupts the data structures used to manage a program's pool of dynamic memory, known as the heap. When a chuck memory is freed using free, the underlying structures that manage the block of memory to be freed manipulate that chunk to place back in to the pool of memory available for allocation. Changing the contents of a freed block of memory can corrupt the underlying data structures in a way that can lead to security vulnerabilities, for instance VU#390044.

When memory is freed its contents may remain intact and accessible. This is because it is at the memory manager's discretion when to reallocate or recycle the freed chunk. The data at the freed location may appear to be valid. However, this can change unexpectedly leading to unintended program behavior.

As a result, it is necessary to guarantee that memory is not written to or read from once it is freed.

Non-compliant Code Example 1

The function build_list is a simple function to create a singly-linked list. The nodes in the linked list are defined as:

struct int_list {
  struct int_list *next;
  int payload;
};

There is an integer payload and a pointer to the next node in the list. In build list, the nodes are allocated and added to the list. The pointer temp is used as a place holder to allocate and set up the node before it is added to the list. However, temp is prematurely freed, in effect de-allocating the list immediately after allocation. When the build_list function returns, list->next refers to freed memory resulting in an error.

/*
 *  list points to the pre-allocated base node in the list
 */
void build_list(const struct int_list *list, size_t size) {
  size_t i;
  struct int_list *c_ptr = NULL;
  list->payload = 42;
  c_ptr = list;
  for (i=0; i < size; i++) {
    struct int_list *temp=malloc(sizeof(struct int_list));
    temp->payload = c_ptr->payload+1;
    c_ptr->next = temp;
    c_ptr = c_ptr->next;
    free(temp);         /* error */
  }
    c_ptr->next = NULL;
}

Compliant Solution 1

Free the memory only when it can be guaranteed that it is no longer used. In the above example this can be done by removing the call to free(temp) in buld_list.

struct int_list {
  struct int_list *next;
  int payload;
};

void main() { /*  build_list(const struct int_list *list) { */
  int i;
  struct int_list *list = malloc(sizeof(struct int_list));
  struct int_list *c_ptr = NULL;
  struct int_list *temp = NULL;
  list->payload = 42;
  c_ptr = list;

  for (i=0; i < 10; i++) {
    temp = malloc(sizeof(struct int_list));
    temp->payload = c_ptr->payload+1;
    c_ptr->next = temp;
    c_ptr = c_ptr->next;
  }
  temp = NULL;
  c_ptr->next = NULL;

  print_list(list);
}
  • No labels