Do not convert convert a pointer value to a pointer type that is more strictly aligned than the referenced type the value actually points to. Different . Different alignments are possible for different types of objects. If the type-checking system is overridden by an explicit cast or the pointer is converted to a void pointer (void *
) and then to a different type, the alignment of an object may be changed.
Subclause The C Standard, 6.3.2.3, paragraph 7 , of the C Standard [ISO/IEC 9899:20112024], states:
A pointer to an object or incomplete type may be converted to a pointer to a different object or incomplete type. If the resulting pointer is not correctly aligned for the referenced the referenced type, the behavior is undefined.
(See also undefined behavior 25 in Annex J of the C Standard.)
If the misaligned pointer is dereferenced, the program may terminate abnormally. On some architectures, the cast alone may cause a loss of information even if the value is not dereferenced if the types involved have differing alignment requirements.
Noncompliant Code Example
In this noncompliant example, the char
pointer pointer &c
is is converted to the more strictly aligned int
pointer pointer ip
. On some implementations, cp
will will not match &c
. As a result, if a pointer to one object type is converted to a pointer to a different object type, the second object type must not require stricter alignment than the first.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <assert.h> void func(void) { char c = 'x'; int *ip = (int *)&c; /* This can lose information */ char *cp = (char *)ip; /* Will fail on some conforming implementations */ assert(cp == &c); } |
Compliant Solution (Intermediate Object)
In this compliant solution, the char
value value is stored into an object of type int
so so that the pointer's value will be properly aligned:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <assert.h> void func(void) { char c = 'x'; int i = c; int *ip = (int *)&i; assert(ip == &i); } |
Compliant Solution (C11, alignas()
)
This compliant solution uses alignas
to align the character c
to the alignment of an integer. As a result, the two pointers point to equally aligned pointer types:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdalign.h>
#include <assert.h>
void func(void) {
/* Align c to the alignment of an int */
alignas(int) char c = 'x';
int *ip = (int *)&c;
char *cp = (char *)ip;
/* Both cp and &c point to equally aligned objects */
assert(cp == &c);
} |
Noncompliant Code Example
The C Standard allows a any object pointer to be cast into to and out of from void *
. As a result, it is possible to silently convert from one pointer type to another without the compiler diagnosing the problem by storing or casting a pointer to void *
and then storing or casting it to the final type. In this noncompliant code example, loop_function()
is passed the char
pointer loopchar_ptr
but returns an object of type int
pointer:
Code Block | ||||
---|---|---|---|---|
| ||||
int *loop_function(void *v_pointer) { /* ... */ return v_pointer; } void func(char *loopchar_ptr) { int *int_ptr = loop_function(loopchar_ptr); /* ... */ } |
This example compiles without warning using GCC 4.8 on Ubuntu Linux 14.04. However, vint_pointer
can be more strictly aligned than an int object of type char *
.
Compliant Solution
Because the input parameter directly influences the return value, and loop_function()
returns an object of type int *
, the formal parameter v_pointer
is redeclared to accept only an object of type int *
:
Code Block | ||||
---|---|---|---|---|
| ||||
int *loop_function(int *v_pointer) { /* ... */ return v_pointer; } void func(int *loop_ptr) { int *int_ptr = loop_function(loop_ptr); /* ... */ } |
...
Noncompliant Code Example
Many Some architectures require that pointers are correctly aligned when accessing objects larger than a byte. There are, however, many places However, it is common in system code where you receive that unaligned data (for example, the network stacks) that needs to must be copied to a properly aligned memory location, such as in this noncompliant code example:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string.h> struct foo_header { int len; /* ... */ }; void func(char *data, size_t offset) { struct foo_header *tmp; struct foo_header header; tmp = (struct foo_header *)(data + offset); memcpy(&header, tmp, sizeof(header)); /* ... */ } |
Unfortunately, the behavior is undefined when you assign Assigning an unaligned value to a pointer that points to references a type that needs to be aligned is undefined behavior. An implementation may notice, for example, that tmp
and header
must be aligned , so it could and use an inlined inline memcpy()
that uses instructions that assume aligned data.
Compliant Solution
This compliant solution does not avoids the use of the foo_header
pointer:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string.h> struct foo_header { int len; /* ... */ }; void func(char *data, size_t offset) { struct foo_header header; memcpy(&header, data + offset, sizeof(header)); /* ... */ } |
Exceptions
EXP36-C-EX0EX1: Some platforms, notably x86, hardware architectures have relaxed requirements with regard to pointer alignment. Using a pointer that is not properly aligned is correctly handled by the platformarchitecture, although the platform may impose there might be a performance penalty. On such a platforman architecture, improper pointer alignment is permitted , as it is but remains an efficiency problem.
The x86 32- and 64-bit architectures usually impose only a performance penalty for violations of this rule, but under some circumstances, noncompliant code can still exhibit undefined behavior. Consider the following program:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdio.h>
#include <stdint.h>
#define READ_UINT16(ptr) (*(uint16_t *)(ptr))
#define WRITE_UINT16(ptr, val) (*(uint16_t *)(ptr) = (val))
void compute(unsigned char *b1, unsigned char *b2,
int value, int range) {
int i;
for (i = 0; i < range; i++) {
int newval = (int)READ_UINT16(b1) + value;
WRITE_UINT16(b2, newval);
b1 += 2;
b2 += 2;
}
}
int main() {
unsigned char buffer1[1024];
unsigned char buffer2[1024];
printf("Compute something\n");
compute(buffer1 + 3, buffer2 + 1, 42, 500);
return 0;
} |
This code tries to read short ints (which are 16 bits long) from odd pairs in a character array, which violates this rule. On 32- and 64-bit x86 platforms, this program should run to completion without incident. However, the program aborts with a SIGSEGV due to the unaligned reads on a 64-bit platform running Debian Linux, when compiled with GCC 4.9.4 using the flags -O3
or -O2 -ftree-loop-vectorize -fvect-cost-model
.
If a developer wishes to violate this rule and use undefined behavior, they must not a security problem.only ensure that the hardware guarantees the behavior of the object code, but they must also ensure that their compiler, along with its optimizer, also respect these guarantees.
EXP36-C-EX2: If a pointer is known to be correctly aligned to the target type, then a cast to that type is permitted. There are several cases where a pointer is known to be correctly aligned to the target type. The pointer could point to an object declared with a suitable alignment specifier. It could point to an object returned by aligned_alloc()
, calloc()
, malloc()
, or realloc()
, as per the C standard, section 7.22.3, paragraph 1 [ISO/IEC 9899:2011].
This compliant solution uses the alignment specifier, which is new to C11, to declare the char
object c
with the same alignment as that of an object of type int
. As a result, the two pointers reference equally aligned pointer types:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdalign.h>
#include <assert.h>
void func(void) {
/* Align c to the alignment of an int */
alignas(int) char c = 'x';
int *ip = (int *)&c;
char *cp = (char *)ip;
/* Both cp and &c point to equally aligned objects */
assert(cp == &c);
} |
Risk Assessment
Accessing a pointer or an object that is not properly aligned can cause a program to crash or give wrong erroneous information, or it can cause slow pointer accesses (if the architecture allows misaligned accesses).
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
EXP36-C | Low | Probable | Medium | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| pointer-cast-alignment | Fully checked | ||||||
Axivion Bauhaus Suite |
| CertC-EXP36 | |||||||
CodeSonar |
| LANG.CAST.PC.OBJ | Cast: Object Pointers | ||||||
Compass/ROSE |
Can detect violations of this rule. However, it does not flag explicit casts to | |||||||||
Coverity |
| MISRA C 2004 Rule 11.4 MISRA C 2012 Rule 11.1 MISRA C 2012 Rule 11.2 MISRA C 2012 Rule 11.5 MISRA C 2012 Rule 11.7 | Implemented | ||||||
Cppcheck Premium |
| premium-cert-exp36-c | Partially implemented | ||||||
| CC2.EXP36 | Fully implemented | |||||||
EDG |
GCC |
|
Can detect some violations of this rule when the | |||||||||
Helix QAC |
| C0326, C3305 C++3033, C++3038 | |||||||
Klocwork |
| MISRA.CAST.OBJ_PTR_TO_OBJ_PTR.2012 | |||||||
LDRA tool suite |
| 94 S |
540
, 606 S |
Partially implemented | |||||||||
Parasoft C/C++test |
| CERT_C-EXP36-a | Do not cast pointers into more strictly aligned pointer types | ||||||
PC-lint Plus |
| 2445 | Partially supported: reports casts directly from a pointer to a less strictly aligned type to a pointer to a more strictly aligned type | ||||||
Polyspace Bug Finder |
| Checks for source buffer misaligned with destination buffer (rule fully covered) | |||||||
PVS-Studio |
| V548, V641, V1032 | |||||||
RuleChecker |
| pointer-cast-alignment | Fully checked |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Key here (explains table format and definitions)
Taxonomy | Taxonomy item | Relationship |
---|---|---|
CERT C |
VOID EXP56 |
-CPP. Do not |
cast pointers into more strictly aligned pointer types | Prior to 2018-01-12: CERT: Unspecified Relationship | |
ISO/IEC TR 24772:2013 | Pointer Casting and Pointer Type Changes [HFC] | Prior to 2018-01-12: CERT: Unspecified Relationship |
ISO/IEC TS 17961 | Converting pointer values to more strictly aligned pointer types [alignconv] | Prior to 2018-01-12: CERT: Unspecified Relationship |
MISRA C:2012 | Rule 11.1 (required) | Prior to 2018-01-12: CERT: Unspecified Relationship |
MISRA C:2012 | Rule 11.2 (required) | Prior to 2018-01-12: CERT: Unspecified Relationship |
MISRA C:2012 | Rule 11.5 (advisory) | Prior to 2018-01-12: CERT: Unspecified Relationship |
MISRA C:2012 | Rule 11.7 (required) | Prior to 2018-01-12: CERT: Unspecified Relationship |
Bibliography
[Bryant 2003] |
[ISO/IEC 9899: |
2024] |
6.3.2.3, "Pointers" | |
[Walfridsson 2003] | Aliasing, Pointer Casts and GCC 3.3 |
...