If ptr
was allocated with an alignment returned from aligned_alloc()
and if realloc()
reallocates memory with a different alignment then, 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 size = 16; size_t resize = 1024; size_t alignment = 1 << 12; int *ptr; int *ptr1; if((ptr = aligned_alloc(align , size)) == NULL) { exit(0); } if((ptr1 = realloc(ptr, resize)) == NULL) { exit(0); }
The resulting program has undefined behavior as the alignment that realloc()
enforces is different from aligned_alloc()
function's alignment.
Implementation Details
When compiled with gcc version 4.1.2 and run on the x86_64-redhat-linux platform the following 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(0); } ptr[0] = 12; ptr[1] = 25; printf("memory aligned to %d bytes\n\n",align); printf("ptr[0] : %p = %d\n",ptr, ptr[0]); printf("ptr[1] : %p = %d\n\n",&ptr[1], ptr[1]); if((ptr1 = realloc((int *)ptr, resize)) == NULL) { exit(0); } printf("After realloc(): \n"); printf("ptr1[0] : %p = %d\n",ptr1, ptr1[0]); printf("ptr1[1] : %p = %d\n\n",&ptr1[1], ptr1[1]); free(ptr1); return 0; }
produces the following (unexpected) output.
memory aligned to 4096 bytes ptr[0] : 0x1f8af000 = 12 ptr[1] : 0x1f8af004 = 25 After realloc(): ptr1[0] : 0x1f8ae010 = 12 ptr1[1] : 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.
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.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
MSC36-C |
high |
probable |
medium |
P12 |
L1 |
References
[[Jones 09]] Section 7.21.3