Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Wiki Markup
Allocating and freeing memory in different modules and levels of abstraction burdens the programmer with tracking the lifetime of that block of memory. This may cause confusion regarding when and if a block of memory has been allocated, or freed, leading to programming defects such as double-free vulnerabilities or writing to un-allocated memory.

...



To avoid these situations, it is recommended that memory be allocated and freed at the same level of abstraction, and preferably in the same code module.

...



The affects of not following this recommendation are best demonstrated by an actual vulnerability. Freeing memory in different modules resulted in a vulnerability in MIT Kerberos 5 [http://web.mit.edu/kerberos/advisories/MITKRB5-SA-2004-002-dblfree.txt]. The problem is the MIT Kerberos 5 code contains error-handling logic, which frees memory allocated by the ASN.1 decoders if pointers to the allocated memory are non-null. However, if a detectable error occurs, the ASN.1 decoders themselves free memory which they have allocated. When some library functions receive errors from the ASN.1 decoders, they also attempt to free, causing a double-free vulnerability.

...



h2. Non-compliant Code Example

...

Compliant Solution 1

References

...

 1

This example attempts to resize the string referenced by {{buf}} to make enough room to append the string {{line}}. However, once in the function {{append()}}, there is no way to determine how {{buf}} was allocated. When {{realloc()}} is called on {{buf}}, since {{buf}} does not point to dynamic memory, an error may occur.
{code}
void append(char *buf, size_t count, size_t size) {
  char *line = " <- THIS IS A LINE";
  int line_len = strlen(line);

  if ((count + line_len) > size)
    buf = realloc(buf,count+line_len);
  strcat(buf,line);
}

h2. Compliant Solution 1

Correcting the above example is an exercise in documentation. Since realloc is used to resize the memory pointed to by buf, the function append has the precondition that buf must point to dynamically allocated memory.
{code}
/\* NOTE: buf must point to dynamically allocated memory \*/
void append(char \*buf, size_t count, size_t size)
{   char *line = " <- THIS IS A LINE";   int line_len = strlen(line);    if ((count + line_len) > size)      buf = realloc(buf,count+line_len);   strncat(buf,line); }
{code}



h2. References

* [Seacord 05|C References#Seacord 05] Chapter 4 Dynamic Memory Management