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

Compare with Current View Page History

« Previous Version 3 Next »

Freeing memory multiple times has similar consequences to accessing memory after it is freed. The underlying data structures that manage the heap can become corrupted in a way that could introduce security vulnerabilities into a program. In practice, these are referred to as double-free vulnerabilities. To eliminate double-free vulnerabilities, it is necessary to guarantee that dynamic memory is freed only once. Programmers should be wary when freeing memory in a loop or conditional statement, if coded incorrectly, these constructs can lead to double-free vulnerabilities.

Non-compliant Code Example 1

In this example, a string of upper case characters is converted to lower all case characters. The pointer to the uppercase string, str is passed to the routine func(). In this routine, a pointer, temp, is set to str and used convert the string "ABCD" to "abcd". Once the string is converted, temp is freed and the function returns. However, because temp references the same storage as str, when temp was freed so was str. As a result, when str is freed a second time in main, freed memory may accessed leading to unpredictable program behavior.

#include <stdlib.h>
#include <stdio.h>

int func(char *str, size_t size) {
  char *temp = str;  /*str and temp reference same location */
  size_t i;
  for (i = 0; i < size-1; i++) temp[i] += 32;
  free(temp);
  return 0;
}

int main(void) {
  size_t size = 5;
  char *str = malloc(size);
  strncpy(str,"ABCD",size);
  printf("%s\n",str); /* 1st printing of str */
  func(str,size);
  free(str);
  return 0;
}

Compliant Solution 1

Only free a pointer to dynamic memory once. This can be accomplished in this example by removing the call to free(str) in main().

#include <stdlib.h>
#include <stdio.h>

int func(char *str, size_t size) {
  char *temp = str;  /*str and temp reference same location */
  size_t i;
  for (i = 0; i < size-1; i++) temp[i] += 32;
  free(temp);
  return 0;
}

int main(void) {
  size_t size = 5;
  char *str = malloc(size);
  strncpy(str,"ABCD",size);
  printf("%s\n",str); /* 1st printing of str */
  func(str,size);
  return 0;
}
  • No labels