Do not modify the alignment of space allocated by aligned_alloc()
by calling realloc()
.
This noncompliant code example returns a pointer to allocated memory that has been aligned to a 4096-byte boundary. If the resize
argument to the realloc()
function is larger than the space referenced by ptr,
realloc()
will likely allocate new memory. This new memory may be suitably aligned so that it can be assigned to a pointer to any type of object with a fundamental alignment requirement, but may not preserve the stricter alignment requirements of the original space.
#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 */ } } |
When compiled with GCC 4.1.2 and run on the x86_64 Red Hat Linux platform, the following code produces the following output:
#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; } |
memory aligned to 4096 bytes ptr = 0x1621b000 After realloc(): ptr1 = 0x1621a010 |
ptr1
is no longer aligned to 4096 bytes.
This compliant solution allocates resize
bytes of new memory with the same alignment as the old memory, copies the original memory content, and then frees the old memory:
#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); } |
Windows defines the _aligned_malloc()
to allocate memory on a specified alignment boundary. The _aligned_realloc()
[MSDN] can be used to change the size of this memory. This compliant solution demonstrates one such usage:
#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 the size and alignment arguments for _aligned_malloc()
are provided in reverse order of the C Standard aligned_alloc()
function.
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 |
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
[ISO/IEC 9899:2011] | Subclause 7.22.3.1, "The aligned_alloc Function" |