...
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
, fp
the 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 |
...