...
An object shall have its stored value accessed only by an lvalue expression that has one of
the following types:
- a type compatible with the effective type of the object,
- a qualified version of a type compatible with the effective type of the object,
- a type that is the signed or unsigned type corresponding to the effective type of the object,
- a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
- an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or
- a character type.
...
In this noncompliant example, a diagnostic is required because an object of type float is incremented through a pointer to int, ip:an int *. Using the maximum units in last position is often done as a way to get the next representable value for a floating-point number. However, accessing an object through a pointer of incompatible types is undefined behavior.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h>
void f(void) {
if (sizeof(int) == sizeof(float)) {
float f = 0.0f;
int *ip = (int *)&f;
printf("float is %f\n", f);
(*ip)++; /* Diagnostic required */
printf("float is %f\n", f);
}
}
|
...
In this compliant solution, the pointer to int, ip has been replaced by a pointer to float, fpthe standard C function nextafterf() is used to round towards the highest representable floating-point value:
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <float.h> #include <math.h> #include <stdio.h> void f(void) { if (sizeof(int) == sizeof(float)) { float f = 0.0f; f float *fp = &f; printf("float is %f\n", f); (*fp)++; nextafterf(f, FLT_MAX); printf("float is %f\n", f); } } |
Noncompliant Code Example
The programmer in this This noncompliant code example is attempting attempts to read from a different union member than the one most recently written to, which is known as type-punning:.
| Code Block | ||||
|---|---|---|---|---|
| ||||
union a_union {
int i;
double d;
};
int f(void) {
union a_union t;
int *ip;
t.d = 3.0;
ip = &t.i;
return *ip;
}
|
However, instead of reading directly from of taking the address of the most-recently written member of the union member, it assigns a pointer, ip, to reference the integer value and returns the value referenced by the pointer. Unfortunately, this is a violation of the strict aliasing rules, and in this case, the , the code takes the address of a member that has not been written to. The compiler may determine that ip refers to some value other than the value stored by t.i and return a value other than the expected value.
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
union a_union {
int i;
double d;
};
int f(void) {
double d = 3.0;
return ((union a_union *) &d)->i;
}
|
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
union a_union {
int i;
double d;
};
int f(void) {
union a_union t;
t.d = 3.0;
return t.i;
}
|
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <stdio.h>
void func(void) {
short a[2];
a[0]=0x1111;
a[1]=0x1111;
*(int *)a = 0x22222222; /* Violation of aliasing rules */
printf("%x %x\n", a[0], a[1]);
/* ... */
} |
When translating this code, an implementation can assume that no access through an integer pointer can change the array a, consisting of shorts. Consequently, printf() may be called with the original values of a[0] and a[1]. The actual behavior is implementation-defined and can change with optimization level.
Implementation Details
Recent versions of GCC turn on the option -fstrict-aliasing (which allows alias-based optimizations) by default with -O2. Some architectures then print "1111 1111" as a result. Without optimization, the executable generates the expected output "2222 2222."
...
Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| PRQA QA-C |
| 0310 | Partially implemented |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
| ISO/IEC TS 17961 | Accessing an object through a pointer to an incompatible type [ptrcomp] |
...
| [Acton 2006] | "Understanding Strict Aliasing" |
| GCC Known Bugs | "C Bugs, Aliasing Issues while Casting to Incompatible Types" |
| GCC Manual | |
| [ISO/IEC 9899:2011] | Subclause 6.5, "Expressions" |
| [Walfridsson 2003] | Aliasing, Pointer Casts and GCC 3.3 |
...