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.
If the misaligned pointer is dereferenced, the program may terminate abnormally. The cast alone may cause a loss of information, even if the value is not dereferenced. For example, the following code is not guaranteed to work conforming C99 implementations, even though no pointers are dereferenced:
char c = 'x'; int *ip = (int *)&c; /* this can lose information */ char *cp = (char *)ip; assert(cp == &c); /* will fail on some conforming implementations */
On some implementations cp
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.
Noncompliant Code Example
C99 (and C90) allows a pointer to be cast into and out of 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, the type checking system is circumvented due to the caveats of void
pointers.
char *loop_ptr; int *int_ptr; int *loop_function(void *v_pointer) { /* ... */ return v_pointer; } int_ptr = loop_function(loop_ptr);
This example compiles without warning. However, v_pointer
may be aligned on a one-byte boundary.
Compliant Solution
Because the input parameter directly influences the return value, and loop_function()
returns an int *
, the formal parameter v_pointer
is redeclared to only accept int *
.
int *loop_ptr; int *int_ptr; int *loop_function(int *v_pointer) { /* ... */ return v_pointer; } int_ptr = loop_function(loop_ptr);
Another solution is to ensure that loop_ptr
points to an object returned by malloc()
because this object is guaranteed to be aligned properly for any need. However, this is a subtlety that is easily missed when the program is modified in the future. It is easier and safer to let the type system document the alignment needs.
Risk Assessment
Accessing a pointer or an object that is no longer on the correct access boundary can cause a program to crash or give wrong information, or may 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
The LDRA tool suite V 7.6.0 can detect violations of this rule.
GCC Compiler can detect some violations of this rule when the -Wcast-align
flag is used.
The EDG Front End to Compass/ROSE can detect some violations of this rule.
Compass/ROSE can detect violations of this rule. However, it does not flag explicit casts to void *
and then back to another pointer type.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Other Languages
This rule appears in the C++ Secure Coding Standard as EXP36-CPP. Do not convert pointers into more strictly aligned pointer types.
References
[[Bryant 03]]
[[ISO/IEC 9899:1999]] Section 6.2.5, "Types"
[[ISO/IEC PDTR 24772]] "HFC Pointer casting and pointer type changes"
[[MISRA 04]] Rules 11.2 and 11.3
EXP35-C. Do not access or modify an array in the result of a function call after a subsequent sequence point 03. Expressions (EXP) EXP37-C. Call functions with the arguments intended by the API