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 [ISO/IEC 9899:2011].
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.
Code Block | ||||
---|---|---|---|---|
| ||||
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
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 |
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.
Code Block | ||||
---|---|---|---|---|
| ||||
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 |
---|---|---|---|---|---|
MEM36-C | low | probable | high | P6 | L3 |
Bibliography
[ISO/IEC 9899:2011] Section 7.22.3.1