Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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.4 paragraph 7 [ISO/IEC 9899:2024], 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

Do not cast away a volatile qualification on a variable type. Casting away the volatile qualification permits the compiler to optimize away operations on the volatile type, consequently negating the use of the volatile keyword in the first place.

...

Code Example

In this noncompliant code example, a volatile object is accessed through a non-volatile-qualified reference, resulting in undefined behavior.:

Code Block
bgColor#FFcccc
langc
#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; /* producesMay warningsproduce ina modernwarning compilersdiagnostic */
  ipp = (int**) &ip; /* constraintConstraint violation; may produce a warning diagnostic */
  *ipp = &i; /* validValid */
  if (*ip != 0) { /* validValid */
    /* ... */
  }
}

The assignment ipp = &ip is unsafe not safe because it would allow 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 it is not possible that i *ip != 0 if i 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++ .NET mode (2003) and on MS Visual Studio 2005. 

This example does not compile on MS Visual Studio 2008. The error message is

Code Block

error C2440: '=' : cannot convert from 'int **' to 'volatile int **'

/TP).

GCC 4.8.1 generates a warning but compiles Version 3.2.2 and Version 4.1.3 of the GCC compiler generate a warning but compile successfully.

Compliant Solution

In this compliant solution, ip is declared as volatile.:

Code Block
bgColor#ccccff
langc
#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

Casting away volatile allows access to Accessing an object with a volatile-qualified type through a reference with a non-volatile reference. This can result in undefined and perhaps unintended program -qualified type is undefined behavior.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

EXP32-C

low

Low

likely

Likely

medium

Medium

P6

L2

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V

pointer-qualifier-cast-volatile

pointer-qualifier-cast-volatile-implicit

Supported indirectly via MISRA C 2012 Rule 11.8
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-EXP32Fully implemented
Clang
Include Page
Clang_V
Clang_V
-Wincompatible-pointer-types-discards-qualifiers
Compass/ROSE




Coverity
Include Page
Coverity_V
Coverity_V

MISRA C 2012 Rule 11.8

Implemented
Cppcheck Premium

Include Page
Cppcheck Premium_V
Cppcheck Premium_V

premium-cert-exp32-cPartially implemented
GCC
Include Page
GCC_V
GCC_V


Can detect violations of this rule when the -Wcast-qual flag is used

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C0312, C0562, C0563, C0673, C0674Fully implemented
Klocwork
Include Page
Klocwork_V
Klocwork_V

CERT.EXPR.VOLATILE.ADDR
CERT.EXPR.VOLATILE.ADDR.PARAM
CERT.EXPR.VOLATILE.PTRPTR

Fully implemented
LDRA tool suite
Include Page
LDRA_V
LDRA_V

344 S

Partially implemented

Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V
CERT_C-EXP32-a

A cast shall not remove any 'const' or 'volatile' qualification from the type of a pointer or reference

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rule EXP32-C

Checks for cast to pointer that removes const or volatile qualification (rule fully covered)

RuleChecker

Include Page
RuleChecker_V
RuleChecker_V

pointer-qualifier-cast-volatile

pointer-qualifier-cast-volatile-implicit
Supported indirectly via MISRA C 2012 Rule 11.8

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

Wiki Markup
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 6.7.3, "Type qualifiers," and Section 6.5.16.1, "Simple assignment"
\[[ISO/IEC PDTR 24772|AA. C References#ISO/IEC PDTR 24772]\] "HFC Pointer casting and pointer type changes"
\[[MISRA 04|AA. C References#MISRA 04]\] Rule 11.5

Related Guidelines

Key here (explains table format and definitions)

Taxonomy

Taxonomy item

Relationship

ISO/IEC TR 24772:2013Pointer Casting and Pointer Type Changes [HFC]Prior to 2018-01-12: CERT: Unspecified Relationship
ISO/IEC TR 24772:2013Type System [IHN]Prior to 2018-01-12: CERT: Unspecified Relationship
MISRA C:2012Rule 11.8 (required)Prior to 2018-01-12: CERT: Unspecified Relationship
CERT CEXP55-CPP. Do not access a cv-qualified object through a cv-unqualified typePrior to 2018-01-12: CERT: Unspecified Relationship

Bibliography

[ISO/IEC 9899:2024]6.7.4, "Type Qualifiers"


...

Image Added Image Added Image AddedEXP31-C. Avoid side effects in assertions      03. Expressions (EXP)       EXP33-C. Do not reference uninitialized memory