Versions Compared

Key

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

The C++ Standard, [dcl.type.cv], paragraph 4 [ISO/IEC 14882-2014], states the following:

Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.

Similarly, paragraph 6 states the following:

What constitutes an access to an object that has volatile-qualified type is implementation-defined. If an attempt is made to refer to an object defined with a volatile-qualified type through the use of a glvalue with a non-volatile-qualified type, the program behavior is undefined.

...

In this noncompliant code example, the function g() is passed a const int &, which is then cast to an int & and modified. Because the referenced value referenced to was previously declared as constas const, the assignment operation results in undefined behavior.

...

In this noncompliant code example, a const-qualified method is called , which that attempts to cache results by casting away the const-qualifier of this. Because s was declared const, the mutation of cachedCalc results cachedValue results in undefined behavior.

Code Block
bgColor#FFcccc
langcpp
#include <iostream>
 
class S {
  int cachedCalccachedValue;
  
  int expensivecompute_computevalue() const;  // expensive
public:
  S() : cachedCalccachedValue(0) {}
  
  // ...  
  int calculateget_value() const {
    if (!cachedCalccachedValue) {
      const_cast<S *>(this)->cachedCalc>cachedValue = expensivecompute_computevalue();  
    }        
    return cachedCalccachedValue;
  }
};

void f() {
  const S s;
  std::cout << s.calculateget_value() << std::endl;
}

Compliant Solution

This compliant solution uses the mutable keyword when declaring cachedCalccachedValue, which allows it cachedValue to be mutated within a const context without triggering undefined behavior:.

Code Block
bgColor#ccccff
langcpp
#include <iostream>
 
class S {
  mutable int cachedCalccachedValue;
  
  int expensivecompute_computevalue() const;  // expensive
public:
  S() : cachedCalccachedValue(0) {}
  
  // ...  
  int calculateget_value() const {
    if (!cachedCalccachedValue) {
      cachedCalccachedValue = expensivecompute_computevalue();  
    }        
    return cachedCalccachedValue;
  }
};

void f() {
  const S s;
  std::cout << s.calculateget_value() << std::endl;
}

Noncompliant Code Example

...

This compliant solution assumes that the volatility of s is required, and so g() is modified to accept a volatile S &:.

Code Block
bgColor#ccccff
langcpp
#include <iostream>

struct S {
  int i;
  
  S(int i) : i(i) {}
};

void g(volatile S &s) {
  std::cout << s.i << std::endl;
}

void f() {
  volatile S s(12);
  g(s);
}

...

EXP55-CPP-EX1: An exception to this rule is allowed when it is necessary to cast away const when invoking a legacy API that does not accept a const argument, provided the function does not attempt to modify the referenced variable. It However, it is always preferable to modify the API to be const-correct when possible, however. For example, the following code casts away the const qualification of INVFNAME in the call to the audit_log() function.

...

If the object is declared as being constant, it may reside in write-protected memory at runtime. Attempting to modify such an object may lead to abnormal program termination or a denial-of-service attack. If an object is declared as being volatile, the compiler can make no assumptions regarding access of that object. Casting away the volatility of an object can result in reads or writes to the object being reordered , or elided entirely, resulting in abnormal program execution.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

EXP55-CPP

Medium

Probable

Medium

P8

L2

Automated Detection

Tool

Version

Checker

Description

   

Astrée

Include Page
Astrée_V
Astrée_V

pointer-qualifier-cast-const
pointer-qualifier-cast-volatile
Partially checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC++-EXP55
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C++3066, C++4671


Klocwork
Include Page
Klocwork_V
Klocwork_V
MISRA.CAST.CONST
LDRA tool suite
Include Page
LDRA_V
LDRA_V

203 S, 242 S, 344 S

Fully implemented

Parasoft C/C++test

Include Page
Parasoft_V
Parasoft_V

CERT_CPP-EXP55-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++: EXP55-CPPChecks for casts that remove cv-qualification of pointer (rule partially covered)
RuleChecker
Include Page
RuleChecker_V
RuleChecker_V
pointer-qualifier-cast-const
pointer-qualifier-cast-volatile
Partially checked
SonarQube C/C++ Plugin
Include Page
SonarQube C/C++ Plugin_V
SonarQube C/C++ Plugin_V
S859
 

Related Vulnerabilities

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

Related Guidelines

Bibliography

[ISO/IEC 14882-2014]Subclause 7.1.6.1, "The cv-qualifiers"
[Sutter
04
2004]Item 94, "Avoid Casting Away const"

...


...

Image Modified Image Modified Image Modified