Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

This noncompliant code example aligns ptr to a 4096 byte boundary whereas the realloc() function aligns the memory to a different alignment (assuming that the sizeof(double) = 8 and sizeof(float) = 4.)

Code Block
bgColor#ffcccc
size_t size = 16;
size_t resize = 1024;
size_t alignment = 1 << 12;
floatint *ptr;
doubleint *ptr1;

if((ptr = aligned_alloc(align , size)) == NULL) {
  exit(0);
}

if((ptr1 = realloc(ptr, size); resize)) == NULL) {
  exit(0);
}

The resulting program has undefined behavior as the alignment that realloc() enforces is different from aligned_alloc() function's alignment.

...

This compliant solution checks that aligned_alloc() has the same alignment as the alignment realloc() function enforces on the memory pointed to by ptr (again assuming that the sizeof(double) = 8 and sizeof(float) = 4).

Code Block
bgColor#ccccff

size_t size = 16;
size_t alignment = 1 << 12;
float *ptr;
double *ptr1;

ptr = aligned_alloc(align , size);

if(align == alignof(ptr1)) {
  ptr1 = realloc(ptr, size);
}

Implementation Details

When compiled with gcc version 4.1.2 and run on the x86_64-redhat-linux platform the following code:

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

int main(void) 
{
  size_t  size = 816;
  size_t re-sizeresize = 1024;
  size_t align = 1 << 12;
  floatint *ptr;
int  double *ptr1;

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

ptr[0] = 12.5;
ptr[1] = 25.5;

printf("memory aligned to %d bytes\n\n",align);
printf("ptr[0]   : %p = %f%d\n",ptr, ptr[0]);
printf("ptr[1]   : %p = %f%d\n\n",&ptr[1], ptr[1]);

if((ptr1 = realloc((int *)ptr, re-sizeresize)) == NULL) {
  exit(0);
}

printf("After realloc(): \n");
printf("ptr1[0]   : %p = %lf%d\n",ptr1, ptrptr1[0]);
printf("ptr1[1]  : %p = %lf%d\n\n",&ptr1[1], ptr1[1]);

free(ptr1);
return 0;
}

...

Code Block
memory aligned to 4096 bytes

ptr[0]   : 0x39bf0000x1f8af000 = 12.500000
ptr[1]   : 0x39bf0040x1f8af004 = 25.500000

After realloc():
ptr1[0]   : 0x39be0100x1f8ae010 = 0.00000012
ptr1[1]  : 0x39be018 = 0.000000
 0x1f8ae014 = 25

Compliant Solution

This compliant solution implements an aligned realloc() function. It allocates new memory of resize bytes with an alignment equal to that of old memory and copies old memory into it. It then frees the old memory.

Code Block
bgColor#ccccff

size_t size = 16;
size_t resize = 1024;
size_t newsize;
int *ptr;
int *ptr1;

if((ptr = aligned_alloc(align , size)) == NULL) {
  exit(0);
}

if((ptr1 = aligned_alloc(align , resize)) == NULL) {
  exit(0);
}

newsize = MIN(size, resize);
if((memcpy(ptr1, ptr, newsize) == NULL) {
 exit(0);
}

free(ptr);

Risk Assessment

Improper alignment can lead to accessing arbitrary memory locations and write into it.

...