According to C99 \[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section The C Standard, 6.7.3, "Type qualifiers," Paragraph 5 (see also [undefined behavior 61 | CC. Undefined Behavior#unb_61] of Appendix J):4, paragraph 7 [ISO/IEC 9899:2024], statesWiki Markup
If an attempt is made to modify an object defined with a
const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined.
See also undefined behavior 61.
There are existing compiler implementations that allow const-qualified values objects to be modified without generating a warning message.
It is also a recommended practice not to cast away a const qualification (see Avoid casting away const qualification because doing so makes it possible to modify const-qualified objects without issuing diagnostics. (See EXP05-C. Do not cast away a const qualification) because doing so makes it easier to modify a const-qualified value without warning. and STR30-C. Do not attempt to modify string literals for more details.)
Noncompliant Code Example
The following well-formed but noncompliant code example borrowed from section 6.5.16.1 of C99 allows a constant value This noncompliant code example allows a constant object to be modified.:
| Code Block | ||||
|---|---|---|---|---|
| ||||
const int char const **cppipp; charint *cpip; charconst constint ci = 'A'42; cpp void func(void) { ipp = &cpip; /* constraintConstraint violation */ *cppipp = &ci; /* validValid */ *cpip = 'B'0; /* validModifies constant i (was 42) */ } |
The first assignment is unsafe because it would allow allows the valid code that follows it to attempt to change the value of the const object c.
Noncompliant Code Example (modifying a string literal)
Similarly to the previous example, the well-formed but noncompliant code example below modifies a constant object after casting away its constness. Compiling the program on a Linux/x64 system doesn't produce any diagnostics even at high warning levels but the generated executable program fails at runtime with SIGESGV.
| Code Block | ||
|---|---|---|
| ||
const char s[] = "foo";
int main() {
*(char*)s = '\0';
}
|
Implementation-Specific Details
i.
Implementation Details
If ipp, , and ipi are declared as automatic If cpp, cp, and c are declared as automatic (stack) variables, this example compiles without warning on warning with Microsoft Visual C++ .NET (2003) and on MS Visual Studio 2005. In both cases, Studio 2013 when compiled in C mode (/TC) and the resulting program changes the value of c. MS Visual Studio 2008 generates an error message. Version 3.2.2 of the GCC compiler i. GCC 4.8.1 generates a warning but compiles. The , and the resulting program changes the value of c i.
If cpp ipp, cp ip, and c and i are declared with static storage duration, this program terminates abnormally for both MS compiles without warning and terminates abnormally with Microsoft Visual Studio 2013, and GCC Version 3.2.2compiles with warning and terminates abnormally with GCC 4.8.1.
Compliant Solution
The compliant solution depends on the intention intent of the programmer. If the intention intent is that the value of c of i is modifiable, then it should not be declared as a constant. If the intention , as in this compliant solution:
| Code Block | ||||
|---|---|---|---|---|
| ||||
int **ipp;
int *ip;
int i = 42;
void func(void) {
ipp = &ip; /* Valid */
*ipp = &i; /* Valid */
*ip = 0; /* Valid */
} |
If the intent is that the value of c of i is not meant to change, then do not write noncompliant code that attempts to modify it.
Risk Assessment
Modifying constant objects through non-constant references results in nonconstant references is undefined behavior 61.
Rule | Severity | Likelihood |
|---|
Detectable | Repairable | Priority | Level |
|---|---|---|---|
EXP40-C | Low |
Unlikely |
Yes |
No | P2 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Astrée |
| assignment-to-non-modifiable-lvalue pointer-qualifier-cast-const pointer-qualifier-cast-const-implicit write-to-constant-memory | Fully checked | ||||||
| Axivion Bauhaus Suite |
| CertC-EXP40 | |||||||
| Coverity |
| PW MISRA C 2004 Rule 11.5 | Implemented | ||||||
| Cppcheck Premium |
| premium-cert-exp40-c | |||||||
| Helix QAC |
| C0563 | |||||||
| LDRA tool suite |
| 582 S | Fully implemented | ||||||
| Parasoft C/C++test |
| CERT_C-EXP40-a | A cast shall not remove any 'const' or 'volatile' qualification from the type of a pointer or reference | ||||||
| Polyspace Bug Finder |
| CERT C: Rule EXP40-C | Checks for write operations on const qualified objects (rule fully covered) | ||||||
| RuleChecker |
| assignment-to-non-modifiable-lvalue pointer-qualifier-cast-const pointer-qualifier-cast-const-implicit | Partially checked | ||||||
| Security Reviewer - Static Reviewer |
| C73 | Fully implemented | ||||||
| TrustInSoft Analyzer |
| mem_access | Exhaustively verified (see the compliant and the non-compliant example). |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
...
Related Guidelines
Key here (explains table format and definitions)
Taxonomy | Taxonomy item | Relationship |
|---|---|---|
| CERT C Secure Coding Standard | EXP05-C. Do not cast away a const qualification | Prior to 2018-01-12: CERT: Unspecified Relationship |
| CERT C Secure Coding Standard | STR30-C. Do not attempt to modify string literals | Prior to 2018-01-12: CERT: Unspecified Relationship |
Bibliography
...
...
| 2024] | Subclause 6.7. |
...
| 4, |
...
| "Type Qualifiers" |
...
qualifiers," and Section 6.5.16.1, "Simple assignment"EXP30-C. Do not depend on order of evaluation between sequence points 03. Expressions (EXP) EXP32-C. Do not access a volatile object through a non-volatile reference