Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

If ptr was allocated with an alignment returned from aligned_alloc() and realloc() reallocates memory with a different alignment, the behavior is undefined. This aligned_alloc()function was introduced in the C11 standard.

Noncompliant Code Example

This noncompliant code example aligns ptr to a 4096-byte boundary, whereas the realloc() function aligns the memory to a suitable, but likely different, alignment:

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

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

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

The resulting program has undefined behavior when the alignment that realloc() enforces is different from that of aligned_alloc().

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

Code Block
#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 %d bytes\n", align);
  printf("ptr = %p\n\n", ptr);

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

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

  free(ptr1);
  return 0;
}

OUTPUT

Code Block
memory aligned to 4096 bytes
ptr = 0x1621b000

After realloc():
ptr1 = 0x1621a010

ptr1 is no longer aligned to 4096 bytes.

Compliant Solution

This compliant solution implements an aligned realloc() function. It allocates resize bytes of new memory with the same alignment as the old memory and then moves the old memory there, then frees the old memory:

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

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

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

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

  free(ptr);
}

Compliant Solution (Windows)

On Windows, aligned allocations happen via calls to _aligned_malloc() and can be reallocated with calls to _aligned_realloc()[MSDN]. This compliant solution demonstrates one such usage:

Code Block
bgColor#ccccff
langc
#include <malloc.h>
 
void func(void) {
  size_t alignment = 1 << 12;
  int *ptr;
  int *ptr1;
 
  /* Original allocation */
  if ((ptr = _aligned_malloc(sizeof(int), alignment))
      == NULL) {
    /* Handle error */
  }
 
  /* Reallocation */
  if ((ptr1 = _aligned_realloc(ptr, 1024, alignment))
      == NULL) {
    _aligned_free(ptr);
    /* Handle error */
  }

  _aligned_free(ptr1);
}

Note that on Windows, _aligned_malloc() takes the size and alignment arguments in reverse order from C's aligned_alloc()

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

Related Vulnerabilities

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

Bibliography

[ISO/IEC 9899:2011Subclause  7.22.3.1, "The aligned_alloc Function"