CertC-EXP32¶
Do not access a volatile object through a nonvolatile reference
Required inputs: IR
An object that has volatile-qualified type may be modified in ways unknown to the implementation or have other unknown side effects. Referencing a volatile object by using a non-volatile lvalue is undefined behavior. The C Standard, 6.7.3 [ ISO/IEC 9899:2011], states
If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.
See undefined behavior 65.
Noncompliant Code Example
In this noncompliant code example, a volatile object is accessed through a non-volatile-qualified reference, resulting in undefined behavior:
#include <stdio.h>
void func(void) {
static volatile int **ipp;
static int *ip;
static volatile int i = 0;
printf("i = %d.\n", i);
ipp = &ip; /* May produce a warning diagnostic */
ipp = (int**) &ip; /* Constraint violation; may produce a warning diagnostic */
*ipp = &i; /* Valid */
if (*ip != 0) { /* Valid */
/* ... */
}
}
The assignment
ipp = &ip is not safe because it allows the valid code that
follows to reference the value of the volatile object
i through the non-volatile-qualified reference
ip. In this example, the compiler may optimize out the entire
if block because
*ip != 0 must be false if the object to which
ip points is not volatile.
Implementation Details
This example compiles without warning on Microsoft Visual Studio 2013 when
compiled in C mode (
/TC) but causes errors when compiled in C++ mode (
/TP).
GCC 4.8.1 generates a warning but compiles successfully.
Compliant Solution
In this compliant solution,
ip is declared
volatile:
#include <stdio.h>
void func(void) {
static volatile int **ipp;
static volatile int *ip;
static volatile int i = 0;
printf("i = %d.\n", i);
ipp = &ip;
*ipp = &i;
if (*ip != 0) {
/* ... */
}
}
Risk Assessment
Accessing an object with a volatile-qualified type through a reference with a non-volatile-qualified type is undefined behavior.
| Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
| EXP32-C | Low | Likely | Medium | P6 | L2 |
Related Guidelines
| Taxonomy | Taxonomy item | Relationship |
|---|---|---|
| ISO/IEC TR 24772:2013 | Pointer Casting and Pointer Type Changes [HFC] | Prior to 2018-01-12: CERT: Unspecified Relationship |
| ISO/IEC TR 24772:2013 | Type System [IHN] | Prior to 2018-01-12: CERT: Unspecified Relationship |
| MISRA C:2012 | Rule 11.8 (required) | Prior to 2018-01-12: CERT: Unspecified Relationship |
| CERT C | EXP55-CPP. Do not access a cv-qualified object through a cv-unqualified type | Prior to 2018-01-12: CERT: Unspecified Relationship |
Bibliography
| [ ISO/IEC 9899:2011] | 6.7.3, "Type Qualifiers" |
Possible Messages
Key |
Text |
Severity |
Disabled |
|---|---|---|---|
cast_adds_const |
Cast adds const qualification |
None |
False |
cast_adds_volatile |
Cast adds volatile qualification |
None |
False |
cast_removes_atomic |
Cast removes _Atomic qualification |
None |
False |
cast_removes_const |
Cast removes const qualification |
None |
False |
cast_removes_volatile |
Cast removes volatile qualification |
None |
False |
implicit_cast_adds_const |
Implicit cast adds const qualification |
None |
False |
implicit_cast_adds_volatile |
Implicit cast adds volatile qualification |
None |
False |
implicit_cast_removes_atomic |
Implicit cast removes _Atomic qualification |
None |
False |
implicit_cast_removes_const |
Implicit cast removes const qualification |
None |
False |
implicit_cast_removes_volatile |
Implicit cast removes volatile qualification |
None |
False |
Options¶
This rule shares the following common options: exclude_in_macros, exclude_messages_in_system_headers, excludes, extend_exclude_to_macro_invocations, includes, justification_checker, languages, post_processing, provider, report_at, severity
The following places define options that affect this rule: Stylechecks, Analysis-GlobalOptions
check_atomic¶
check_atomic : bool = False
check_const¶
check_const : bool = False
check_volatile¶
check_volatile : bool = True
only_top_level¶
only_top_level : bool = False