CertC++-MEM36

Do not modify the alignment of objects by calling realloc()

Required inputs: IR, StaticSemanticAnalysis

Do not invoke realloc() to modify the size of allocated objects that have stricter alignment requirements than those guaranteed by malloc(). Storage allocated by a call to the standard aligned_alloc() function, for example, can have stricter than normal alignment requirements. The C standard requires only that a pointer returned by realloc() be suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement.

Noncompliant Code Example

This noncompliant code example returns a pointer to allocated memory that has been aligned to a 4096-byte boundary.  If the resize argument to the realloc() function is larger than the object referenced by ptr, then realloc() will allocate new memory that is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement but may not preserve the stricter alignment of the original object.

#include <stdlib.h>
 
void func(void) {
  size_t resize = 1024;
  size_t alignment = 1 << 12;
  int *ptr;
  int *ptr1;

  if (NULL == (ptr = (int *)aligned_alloc(alignment, sizeof(int)))) {
    /* Handle error */
  }

  if (NULL == (ptr1 = (int *)realloc(ptr, resize))) {
    /* Handle error */
  }
}
Implementation Details

When compiled with GCC 4.1.2 and run on the x86_64 Red Hat Linux platform, the following code produces the following output:

CODE

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

int main(void) {
  size_t  size = 16;
  size_t resize = 1024;
  size_t align = 1 << 12;
  int *ptr;
  int *ptr1;

  if (posix_memalign((void **)&ptr, align , size) != 0) {
    exit(EXIT_FAILURE);
  }

  printf("memory aligned to %zu bytes\n", align);
  printf("ptr = %p\n\n", ptr);

  if ((ptr1 = (int*) realloc((int *)ptr, resize)) == NULL) {
    exit(EXIT_FAILURE);
  }

  puts("After realloc(): \n");
  printf("ptr1 = %p\n", ptr1);

  free(ptr1);
  return 0;
}

OUTPUT

memory aligned to 4096 bytes
ptr = 0x1621b000

After realloc():
ptr1 = 0x1621a010

ptr1 is no longer aligned to 4096 bytes.

Compliant Solution

This compliant solution  allocates resize bytes of new memory with the same alignment as the old memory, copies the original memory content, and then frees the old memory. This solution has implementation-defined behavior because it depends on whether extended alignments in excess of _Alignof (max_align_t) are supported and the contexts in which they are supported. If not supported, the behavior of this compliant solution is undefined.

#include <stdlib.h>
#include <string.h>
 
void func(void) {
  size_t resize = 1024;
  size_t alignment = 1 << 12;
  int *ptr;
  int *ptr1;

  if (NULL == (ptr = (int *)aligned_alloc(alignment,
                                          sizeof(int)))) {
    /* Handle error */
  }

  if (NULL == (ptr1 = (int *)aligned_alloc(alignment,
                                           resize))) {
    /* Handle error */
  }

  if (NULL == memcpy(ptr1, ptr, sizeof(int))) {
    /* Handle error */
  }

  free(ptr);
}
Compliant Solution (Windows)

Windows defines the _aligned_malloc() function to allocate memory on a specified alignment boundary.  The _aligned_realloc() [ MSDN] can be used to change the size of this memory. This compliant solution demonstrates one such usage:

#include <malloc.h>

void func(void) {
  size_t alignment = 1 << 12;
  int *ptr;
  int *ptr1;

  /* Original allocation */
  if (NULL == (ptr = (int *)_aligned_malloc(sizeof(int),
                                            alignment))) {
    /* Handle error */
}

  /* Reallocation */
  if (NULL == (ptr1 = (int *)_aligned_realloc(ptr, 1024,
                                              alignment))) {
    _aligned_free(ptr);
    /* Handle error */
  }

  _aligned_free(ptr1);
}

The  size and alignment arguments for _aligned_malloc() are provided in reverse order of the C Standard aligned_alloc() function.

Risk Assessment

Improper alignment can lead to arbitrary memory locations being accessed and written to.

Recommendation Severity Likelihood Remediation Cost Priority Level
MEM36-C Low Probable High P2 L3
Bibliography
[ ISO/IEC 9899:2011]  7.22.3.1, "The  aligned_alloc Function"
[ MSDN] aligned_malloc()
Excerpt from SEI CERT C++ Coding Standard [https://cmu-sei.github.io/secure-coding-standards/sei-cert-c-coding-standard/rules/memory-management-mem/mem36-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

realloc_aligned

Do not modify the alignment of objects by calling realloc().

None

False

Options

aligned_allocators

aligned_allocators : set[bauhaus.analysis.config.FunctionName] = {'_aligned_malloc', 'aligned_alloc', 'posix_memalign'}

Functions that allocate aligned memory.
 

realloc_functions

realloc_functions : set[bauhaus.analysis.config.FunctionName] = {'realloc'}

Functions that reallocate without allowing for aligned memory. The first argument must be the pointer to reallocate.