Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Updated references from C11->C23

If ptr was allocated with an alignment returned from Do not invoke realloc() to modify the size of allocated objects that have stricter alignment requirements than those guaranteed by malloc(). Storage allocated by a call to the standard aligned_alloc() and if realloc() reallocates memory with a different alignment then, the behavior is undefined.

Wiki Markup
This rule only applies to compilers that conform to the (emerging) C1X standard \[[Jones 09|AA. C References#Jones 09]\].

function, for example, can have stricter than normal alignment requirements. The C standard requires only that a pointer returned by realloc() be suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement.

Noncompliant Code Example

This noncompliant code example aligns ptr returns a pointer to allocated memory that has been aligned to a 4096-byte boundary whereas .  If the resize argument to the realloc() function aligns the memory to a different alignment (assuming that the sizeof(double) = 8 and sizeof(float) = 4.)is larger than the object referenced by ptr, then realloc() will allocate new memory that is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement but may not preserve the stricter alignment of the original object.

Code Block
bgColor#ffcccc
langc
#include <stdlib.h>
 
void func(void) {
  size_t sizeresize = 161024;
  size_t alignment = 1 << 12;
float  int *ptr;
double  int *ptr1;
  
ptr  =if aligned_alloc(alignNULL , size);
ptr1== (ptr = realloc(ptr,int size);

...

*)aligned_alloc(

...

Compliant Solution

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);
}
alignment, sizeof(int)))) {
    /* Handle error */
  }

  if (NULL == (ptr1 = (int *)realloc(ptr, resize))) {
    /* Handle error */
  }
}

Implementation Details

When compiled with gcc version GCC 4.1.2 and run on the x86_64 -redhat-linux platform 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 = 101024;
  size_t align = 1 << 12;
  floatint *ptr;
  doubleint *ptr1;

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

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

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

  if ((ptr1 = (int*) realloc((int *)ptr, 1024resize)) == NULL) {
    exit(0EXIT_FAILURE);
  }

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

  free(ptr1);
  return 0;
}

...

OUTPUT

Code Block

memory aligned to 4096 bytes

ptr[0] = 0x1621b000

After realloc(): 0xb43c000 = 12.500000
ptr[1]   : 0xb43c004 = 25.500000

After realloc():
ptr1[0]   : 0xb43c000 = 12.500000
ptr1[1]  : 0xb43c008 = 0.000000

The value at ptr[1] remains the same after realloc()
ptr[1]  : 0xb43c004 = 25.500000


ptr1 = 0x1621a010

ptr1 is no longer aligned to 4096 bytes.

Compliant Solution

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. This solution has implementation-defined behavior because it depends on whether extended alignments in excess of _Alignof (max_align_t) are supported and the contexts in which they are supported. If not supported, the behavior of this compliant solution is undefined.

Code Block
bgColor#ccccff
langc
#include <stdlib.h>
#include <string.h>
 
void func(void) {
  size_t resize = 1024;
  size_t alignment = 1 << 12;
  int *ptr;
  int *ptr1;

  if (NULL == (ptr = (int *)aligned_alloc(alignment,
                                          sizeof(int)))) {
    /* Handle error */
  }

  if (NULL == (ptr1 = (int *)aligned_alloc(alignment,
                                           resize))) {
    /* Handle error */
  }
  
  if (NULL == memcpy(ptr1, ptr, sizeof(int))) {
    /* Handle error */
  }
  
  free(ptr);
}

Compliant Solution (Windows)

Windows defines the _aligned_malloc() function 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:

Code Block
bgColor#ccccff
langc
#include <malloc.h>

void func(void) {
  size_t alignment = 1 << 12;
  int *ptr;
  int *ptr1;

  /* Original allocation */
  if (NULL == (ptr = (int *)_aligned_malloc(sizeof(int),
                                            alignment))) {
    /* Handle error */
}

  /* Reallocation */
  if (NULL == (ptr1 = (int *)_aligned_realloc(ptr, 1024,
                                              alignment))) {
    _aligned_free(ptr);
    /* Handle error */
  }

  _aligned_free(ptr1);
}

The size and alignment arguments for _aligned_malloc() are provided in reverse order of the C Standard aligned_alloc() function.

Risk Assessment

Improper alignment can lead to accessing arbitrary memory locations and write into itbeing accessed and written to.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

MSC36

MEM36-C

medium

probable

medium

P8

L2

References

Low

Probable

High

P2

L3

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V

Supported, but no explicit checker
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-MEM36Fully implemented
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

BADFUNC.REALLOC

Use of realloc

Cppcheck Premium

Include Page
Cppcheck Premium_V
Cppcheck Premium_V

premium-cert-mem36-cFully implemented
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C5027

C++5034


Klocwork
Include Page
Klocwork_V
Klocwork_V

AUTOSAR.STDLIB.MEMORY


LDRA tool suite
Include Page
LDRA_V
LDRA_V
44 SEnhanced enforcement
Parasoft C/C++test

Include Page
Parasoft_V
Parasoft_V

CERT_C-MEM36-aDo not modify the alignment of objects by calling realloc()

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule MEM36-CChecks for alignment change after memory allocation (rule fully covered)

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Bibliography

[ISO/IEC 9899:20247.24.3.1, "The aligned_alloc Function"
[MSDN]aligned_malloc()


...

Image Added Image Added Image Added Wiki Markup\[[Jones 09|AA. C References#Jones 09]\] Section 7.21.3