CertC++-MEM34

Only free memory allocated dynamically

Required inputs: IR, StaticSemanticAnalysis

The pointer argument to the free or realloc function does not match a pointer earlier returned by a memory management function, or the space has been deallocated by a call to free or realloc.

See also undefined behavior 179.

Freeing memory that is not allocated dynamically can result in heap corruption and other serious errors. Do not call  free() on a pointer other than one returned by a standard memory allocation function, such as malloc(), calloc(), realloc(), or aligned_alloc().

A similar situation arises when realloc() is supplied a pointer to non-dynamically allocated memory. The realloc() function is used to resize a block of dynamic memory. If realloc() is supplied a pointer to memory not allocated by a standard memory allocation function, the behavior is undefined. One consequence is that the program may terminate abnormally.

This rule does not apply to null pointers. The C Standard guarantees that if free() is passed a null pointer, no action occurs.

Noncompliant Code Example

This noncompliant code example sets c_str to reference either dynamically allocated memory or a statically allocated string literal depending on the value of argc. In either case, c_str is passed as an argument to free(). If anything other than dynamically allocated memory is referenced by c_str, the call to free(c_str) is erroneous.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
 
enum { MAX_ALLOCATION = 1000 };

int main(int argc, const char *argv[]) {
  char *c_str = NULL;
  size_t len;

  if (argc == 2) {
    len = strlen(argv[1]) + 1;
    if (len > MAX_ALLOCATION) {
      /* Handle error */
    }
    c_str = (char *)malloc(len);
    if (c_str == NULL) {
      /* Handle error */
    }
    strcpy(c_str, argv[1]);
  } else {
    c_str = "usage: $>a.exe [string]";
    printf("%s\n", c_str);
  }
  free(c_str);
  return 0;
}
Compliant Solution

This compliant solution eliminates the possibility of c_str referencing memory that is not allocated dynamically when passed to free():

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
 
enum { MAX_ALLOCATION = 1000 };

int main(int argc, const char *argv[]) {
  char *c_str = NULL;
  size_t len;

  if (argc == 2) {
    len = strlen(argv[1]) + 1;
    if (len > MAX_ALLOCATION) {
      /* Handle error */
    }
    c_str = (char *)malloc(len);
    if (c_str == NULL) {
      /* Handle error */
    }
    strcpy(c_str, argv[1]);
  } else {
    printf("%s\n", "usage: $>a.exe [string]");
    return EXIT_FAILURE;
  }
  free(c_str);
  return 0;
}
Noncompliant Code Example ( realloc())

In this noncompliant example, the pointer parameter to realloc(), buf, does not refer to dynamically allocated memory:

#include <stdlib.h>
 
enum { BUFSIZE = 256 };

void f(void) {
  char buf[BUFSIZE];
  char *p = (char *)realloc(buf, 2 * BUFSIZE);
  if (p == NULL) {
    /* Handle error */
  }
}
Compliant Solution ( realloc())

In this compliant solution, buf refers to dynamically allocated memory:

#include <stdlib.h>
 
enum { BUFSIZE = 256 };

void f(void) {
  char *buf = (char *)malloc(BUFSIZE * sizeof(char));
  char *p = (char *)realloc(buf, 2 * BUFSIZE);
  if (p == NULL) {
    /* Handle error */
  }
}

Note that  realloc() will behave properly even if  malloc() failed, because when given a null pointer,  realloc() behaves like a call to  malloc().

Risk Assessment

The consequences of this error depend on the implementation, but they range from nothing to arbitrary code execution if that memory is reused by malloc()

Rule Severity Likelihood Remediation Cost Priority Level
MEM34-C High Likely Medium P18 L1
Related Guidelines
Taxonomy Taxonomy item Relationship
CERT C Secure Coding Standard MEM31-C. Free dynamically allocated memory when no longer needed Prior to 2018-01-12: CERT: Unspecified Relationship
CERT C MEM51-CPP. Properly deallocate dynamically allocated resources Prior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC TS 17961 Reallocating or freeing memory that was not dynamically allocated [xfree] Prior to 2018-01-12: CERT: Unspecified Relationship
CWE 2.11 CWE-590, Free of Memory Not on the Heap 2017-07-10: CERT: Exact
Bibliography
[ ISO/IEC 9899:2011] Subclause J.2, "Undefined Behavior"
[ Seacord 2013b] Chapter 4, "Dynamic Memory Management"
Excerpt from SEI CERT C++ Coding Standard [https://cmu-sei.github.io/secure-coding-standards/sei-cert-c-coding-standard/rules/memory-management-mem/mem34-c], Copyright (C) 1995-2026 Carnegie Mellon University. See section 9.4. "3rd-Party Licenses" in the documentation for full details.

Possible Messages

Key

Text

Severity

Disabled

possible_stack_free

{name0} possibly released by call to {node0} is a stack or static object

None

False

stack_free

{name0} released by call to {node0} is a stack or static object

None

False

Options

resources

resources

Type: set[str]

Default: {'C++ArrayHeapMemory', 'C++HeapMemory', 'CudaAsyncMemory', 'CudaDeviceMemory', 'CudaDriverAsyncMemory', 'CudaHostMemory', 'CudaManagedMemory', 'HeapMemory', 'UniquePtrHeapMemory'}

Deallocator calls of these resources are checked for being called with a stack/static object; the names are a selection of rules in the Resources group.
 

witness_paths

witness_paths : bool = True

Whether witness paths should be determined and included in the issue.