You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 55 Next »

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

This rule only applies to compilers that conform to the (emerging) C1X standard [[Jones 09]].

Noncompliant Code Example

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

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 because the alignment that realloc() enforces is different from that of aligned_alloc().

Implementation Details

When compiled with GCC Version 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 %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

memory aligned to 4096 bytes
ptr = 0x1621b000

After realloc():
ptr1 = 0x1621a010

Unfortunately, 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, consequently freeing up the old memory.

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);

Risk Assessment

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

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

MSC36-C

high

probable

medium

P12

L1

References

[[Jones 09]] Section 7.21.3
[aligned_alloc()] 7.20.3.5


MSC35-C. Do not include any executable statements inside a switch statement before the first case label      49. Miscellaneous (MSC)      

  • No labels