Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Substantive changes

Accessing previously dynamically allocated memory after it has been deallocated may corrupt the data structures used to manage the free store or other types of storage. References to memory that has Evaluating pointers into memory that have been deallocated by a memory management function, including dereferencing, acting as an operand of an arithmetic operation, type casting, or using the pointer as the right-hand side of an assignment, is undefined behavior. Pointers to memory that have been deallocated are referred to as as dangling pointers. Accessing a dangling pointer can result in exploitable exploitable vulnerabilities.

Reading a pointer to deallocated memory is undefined because the pointer value is indeterminate and may have a trap representation . In the latter case, doing so may cause a hardware trap.

When memory is deallocated, its contents may remain intact and accessible because it is at the memory manager's discretion when to reallocate or recycle the deallocated chunk. The data at the deallocated location may appear valid. However, this can change unexpectedly, leading to unintended program behavior. As a result, it is necessary to guarantee that memory is not It is at the memory manager's discretion when to reallocate or recycle the freed memory. When memory is freed, all pointers into it become invalid, and its contents might either be returned to the operating system, making the freed space inaccessible, or remain intact and accessible. As a result, the data at the freed location can appear to be valid but change unexpectedly. Consequently, memory must not be written to or read from once it is deallocatedfreed.anchor nce_free nce_free

Noncompliant Code Example

...

This example from Kernighan and Ritchie [Kernighan 88] shows both the incorrect and correct techniques for removing items from a linked list. The incorrect solution, clearly marked as wrong in the book, is bad because p is deallocated before the p->next is executed, so p->next reads memory that has already been deallocated.

...

bgColor#FFCCCC
langcpp

...

(

...

Compliant Solution (free)

Kernighan and Ritchie also show the correct solution. To correct this error, a reference to p->next is stored in q before freeing p.

Code Block
bgColor#ccccff
langcpp
for (p = head; p != NULL; p = q) {
  q = p->next;
  free(p);
}
head = NULL;

...

Noncompliant Code Example (new and deletenew and delete)

In this noncompliant code example, buff s is written to dereferenced after it has been deallocated. These vulnerabilities can be easily exploited to If this access results in a write-after-free, the vulnerability can be exploited to run arbitrary code with the permissions of the vulnerable process and are seldom this obvious. Typically Typically, dynamic memory allocations and deallocations are far removed, making it difficult to recognize and diagnose such problems.

Code Block
bgColor#FFCCCC
langcpp
int main(int argc, const char *argv[]#include <new>
 
struct S {
  void f();
};
 
void f() {
  charS *buff;

  buffs = new char[BUFSIZ]S;
  // ...
  delete[] buffs;
  // ...
  strncpy(buff, argv[1], BUFSIZ-1s->f();
}

...

Compliant Solution (new and  and delete)

In this compliant solution, the dynamically allocated memory isn't deallocated until it is no longer required.:

Code Block
bgColor#ccccff
langcpp
int main(int argc, const char *argv[]#include <new>

struct S {
  void f();
};

void f() {
  charS *buff;

  buffs = new char[BUFSIZ]S;
  // ...
  strncpy(buff, argv[1], BUFSIZ-1);
  // ...
  delete[] buff;
  buff = nullptr;
}

...


  s->f();
  delete s;
}

Compliant Solution (Automatic Storage Duration)

When possible, it is preferred to use automatic storage duration instead of dynamic storage duration. Since s is not required to live beyond the scope of f(), this compliant solution uses automatic storage duration to limit the lifetime of s to the scope of f():

Code Block
bgColor#ccccff
langcpp
struct S {
  void f();
};

void f() {
  S s;
  // ...
  s.f();
}

...

Noncompliant Code Example (std::unique_ptr)

In the following noncompliant code example, the dynamically allocated memory managed by the buff object is accessed after it has been implicitly deallocated by the object's destructor.:

Code Block
bgColor#ffcccc
langcpp
#include <iostream>
#include <memory>
#include <cstring>
 
int main(int argc, const char *argv[]) {
  const char *s = "";

  if (argc > 1) {
  <  argc)enum { BUFFER_SIZE = 32 };
    std::unique_ptr<char[]> buff (new char [BUFSIZBUFFER_SIZE]);
    // ...
    s = std::strncpy(buff.get(), argv[1], BUFSIZBUFFER_SIZE - 1);
  }

  std::cout << s << '\n'std::endl;
}

...

...

Compliant Solution (std::unique_ptr)

In this compliant solution, the lifetime of the buff object extends past the point the memory managed by the object is accessed.:

Code Block
bgColor#ccccff
langcpp
#include <iostream>
#include <memory>
#include <cstring>
 
int main(int argc, const char *argv[]) {
  std::unique_ptr<char[]> buff;
  const char *s = "";

  if (1argc <> argc1) {
    enum { BUFFER_SIZE = 32 };
    buff.reset(new char [BUFSIZBUFFER_SIZE]);
    // ...
    s = std::strncpy(buff.get(), argv[1], BUFFER_SIZE BUFSIZ- 1);
  }

  std::cout << s << '\n';
}
 std::endl;
}

Compliant Solution

In this compliant solution, a variable with automatic storage duration of type std::string is used in place of the std::unique_ptr<char[]>, which reduces the complexity and increases the security of the solution:

Code Block
bgColor#ccccff
langcpp
#include <iostream>
#include <string>
 
int main(int argc, const char *argv[]) {
  std::string str;

  if (argc > 1) {
    str = argv[1];
  }

  std::cout << str << std::endl;
}

Noncompliant Code Example (std::string::c_str())

...

Code Block
bgColor#ffcccc
langcpp
#include <string>
 
std::string someStringReturningFunction();
/* ... */
void displayString(const char *);
 
void f() {
  const char *str = someStringReturningFunction().c_str();
  displayString(str);  /* Undefined behavior */

}

Compliant solution (std::string::c_str())

In this compliant solution, a local copy of the string returned by someStringReturningFunction() is made on the stack, which means the that ensures the string str will be valid when the call to displayString is made:

Code Block
bgColor#ccccff
langcpp
#include <string>
 
std::string someStringReturningFunction();
void displayString( const char * s );
std::string someStringReturningFunction
void f(); {
/* ... */
std::string str = someStringReturningFunction();
  const char *str = str.c_str();
  displayString(str);  /* ok */
}

Risk Assessment

Reading previously dynamically allocated memory after it has been deallocated can lead to abnormal program termination and denial-of-service attacks. Writing memory that has been deallocated can lead to the execution of arbitrary code with the permissions of the vulnerable process.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

MEM30-CPP

highHigh

likelyLikely

mediumMedium

P18

L1

Automated Detection

Tool

...

Version

...

Fortify SCA Version 5.0 can detect violations of this rule.

Splint Version 3.1.1 can detect violations of this rule.

Compass/ROSE can detect violations of the rule.

...

Checker

Description

Compass/ROSE

 

 

 

Coverity

Include Page
Coverity_V
Coverity_V

USE_AFTER_FREE

...

Can detect the specific instances where memory is deallocated more than once or

...

read/

...

written to the target of a freed pointer

Fortify SCA

5.0

...

Double Free

 

Klocwork

Include Page
Klocwork_V
Klocwork_V

UFM.DEREF.MIGHT

...


UFM.DEREF.MUST

...


UFM.

...

PARAMPASS.MIGHT

...


UFM.PARAMPASS.MUST

...


UFM.RETURN.MIGHT

...


UFM.RETURN.MUST

...


UFM.USE.MIGHT

...


UFM.USE.MUST

...

 

LDRA tool suite

Include Page
LDRA_V
LDRA_V

51 D

Fully implemented

Splint

Include Page
Splint_V
Splint_V

 

 

Related Vulnerabilities

VU#623332 describes a double-free vulnerability in the MIT Kerberos 5 function krb5_recvauth()

Search for other vulnerabilities resulting  resulting from the violation of this rule on the the CERT website.

Other Languages

...

Related Guidelines

...

...

Bibliography

...

MITRE CWE

CWE-415, Double Free
CWE-416, Use After Free

Bibliography

...

14882-2014]3.7.4.2, "Deallocation Functions"
[Seacord 2013b]Chapter 4, "Dynamic Memory Management"

[Viega 05] Section 5.2.19, "Using freed memory"