|
| 1 | +# EXP40-C: Do not modify constant objects |
| 2 | + |
| 3 | +This query implements the CERT-C rule EXP40-C: |
| 4 | + |
| 5 | +> Do not modify constant objects |
| 6 | +
|
| 7 | + |
| 8 | +## Description |
| 9 | + |
| 10 | +The C Standard, 6.7.3, paragraph 6 \[[IS](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO-IEC9899-2011)[O/IEC 9899:2011](https://wiki.sei.cmu.edu/confluence/display/c/AA.+Bibliography#AA.Bibliography-ISO-IEC9899-2011)\], states |
| 11 | + |
| 12 | +> If an attempt is made to modify an object defined with a `const`-qualified type through use of an [lvalue](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-lvalue) with non-`const`-qualified type, the behavior is undefined. |
| 13 | +
|
| 14 | + |
| 15 | +See also [undefined behavior 64](https://wiki.sei.cmu.edu/confluence/display/c/CC.+Undefined+Behavior#CC.UndefinedBehavior-ub_64). |
| 16 | + |
| 17 | +There are existing compiler [implementations](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-implementation) that allow `const`-qualified objects to be modified without generating a warning message. |
| 18 | + |
| 19 | +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](https://wiki.sei.cmu.edu/confluence/display/c/EXP05-C.+Do+not+cast+away+a+const+qualification) and [STR30-C. Do not attempt to modify string literals](https://wiki.sei.cmu.edu/confluence/display/c/STR30-C.+Do+not+attempt+to+modify+string+literals) for more details.) |
| 20 | + |
| 21 | +## Noncompliant Code Example |
| 22 | + |
| 23 | +This noncompliant code example allows a constant object to be modified: |
| 24 | + |
| 25 | +```cpp |
| 26 | +const int **ipp; |
| 27 | +int *ip; |
| 28 | +const int i = 42; |
| 29 | + |
| 30 | +void func(void) { |
| 31 | + ipp = &ip; /* Constraint violation */ |
| 32 | + *ipp = &i; /* Valid */ |
| 33 | + *ip = 0; /* Modifies constant i (was 42) */ |
| 34 | +} |
| 35 | +``` |
| 36 | +The first assignment is unsafe because it allows the code that follows it to attempt to change the value of the `const` object `i`. |
| 37 | +
|
| 38 | +**Implementation Details** |
| 39 | +
|
| 40 | +If `ipp`, `ip`, and `i` are declared as automatic variables, this example compiles without warning with Microsoft Visual Studio 2013 when compiled in C mode (`/TC`) and the resulting program changes the value of `i`. GCC 4.8.1 generates a warning but compiles, and the resulting program changes the value of `i`. |
| 41 | +
|
| 42 | +If `ipp`, `ip`, and `i` are declared with static storage duration, this program compiles without warning and terminates abnormally with Microsoft Visual Studio 2013, and compiles with warning and terminates abnormally with GCC 4.8.1. |
| 43 | +
|
| 44 | +## Compliant Solution |
| 45 | +
|
| 46 | +The compliant solution depends on the intent of the programmer. If the intent is that the value of `i` is modifiable, then it should not be declared as a constant, as in this compliant solution: |
| 47 | +
|
| 48 | +```cpp |
| 49 | +int **ipp; |
| 50 | +int *ip; |
| 51 | +int i = 42; |
| 52 | +
|
| 53 | +void func(void) { |
| 54 | + ipp = &ip; /* Valid */ |
| 55 | + *ipp = &i; /* Valid */ |
| 56 | + *ip = 0; /* Valid */ |
| 57 | +} |
| 58 | +``` |
| 59 | +If the intent is that the value of i is not meant to change, then do not write noncompliant code that attempts to modify it. |
| 60 | + |
| 61 | +## Risk Assessment |
| 62 | + |
| 63 | +Modifying constant objects through nonconstant references is [undefined behavior](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-undefinedbehavior). |
| 64 | + |
| 65 | +<table> <tbody> <tr> <th> Rule </th> <th> Severity </th> <th> Likelihood </th> <th> Remediation Cost </th> <th> Priority </th> <th> Level </th> </tr> <tr> <td> EXP40-C </td> <td> Low </td> <td> Unlikely </td> <td> Medium </td> <td> <strong>P2</strong> </td> <td> <strong>L3</strong> </td> </tr> </tbody> </table> |
| 66 | + |
| 67 | + |
| 68 | +## Automated Detection |
| 69 | + |
| 70 | +<table> <tbody> <tr> <th> Tool </th> <th> Version </th> <th> Checker </th> <th> Description </th> </tr> <tr> <td> <a> Astrée </a> </td> <td> 22.04 </td> <td> <strong>assignment-to-non-modifiable-lvalue</strong> <strong>pointer-qualifier-cast-const</strong> <strong>pointer-qualifier-cast-const-implicit</strong> <strong>write-to-constant-memory</strong> </td> <td> Fully checked </td> </tr> <tr> <td> <a> Axivion Bauhaus Suite </a> </td> <td> 7.2.0 </td> <td> <strong>CertC-EXP40</strong> </td> <td> </td> </tr> <tr> <td> <a> Coverity </a> </td> <td> 2017.07 </td> <td> <strong>PW</strong> <strong>MISRA C 2004 Rule 11.5</strong> </td> <td> Implemented </td> </tr> <tr> <td> <a> Helix QAC </a> </td> <td> 2022.3 </td> <td> <strong>C0563</strong> </td> <td> </td> </tr> <tr> <td> <a> LDRA tool suite </a> </td> <td> 9.7.1 </td> <td> <strong>582 S</strong> </td> <td> Fully implemented </td> </tr> <tr> <td> <a> Parasoft C/C++test </a> </td> <td> 2022.1 </td> <td> <strong>CERT_C-EXP40-a</strong> </td> <td> A cast shall not remove any 'const' or 'volatile' qualification from the type of a pointer or reference </td> </tr> <tr> <td> <a> Polyspace Bug Finder </a> </td> <td> R2022b </td> <td> <a> CERT C: Rule EXP40-C </a> </td> <td> Checks for write operations on const qualified objects (rule fully covered) </td> </tr> <tr> <td> <a> PRQA QA-C </a> </td> <td> 9.7 </td> <td> <strong>0563</strong> </td> <td> Partially implemented </td> </tr> <tr> <td> <a> RuleChecker </a> </td> <td> 22.04 </td> <td> <strong>assignment-to-non-modifiable-lvalue</strong> <strong>pointer-qualifier-cast-const</strong> <strong>pointer-qualifier-cast-const-implicit</strong> </td> <td> Partially checked </td> </tr> <tr> <td> <a> TrustInSoft Analyzer </a> </td> <td> 1.38 </td> <td> <strong>mem_access</strong> </td> <td> Exhaustively verified (see <a> the compliant and the non-compliant example </a> ). </td> </tr> </tbody> </table> |
| 71 | + |
| 72 | + |
| 73 | +## Related Vulnerabilities |
| 74 | + |
| 75 | +Search for [vulnerabilities](https://wiki.sei.cmu.edu/confluence/display/c/BB.+Definitions#BB.Definitions-vulnerability) resulting from the violation of this rule on the [CERT website](https://www.kb.cert.org/vulnotes/bymetric?searchview&query=FIELD+KEYWORDS+contains+EXP40-C). |
| 76 | + |
| 77 | +## Related Guidelines |
| 78 | + |
| 79 | +[Key here](https://wiki.sei.cmu.edu/confluence/display/c/How+this+Coding+Standard+is+Organized#HowthisCodingStandardisOrganized-RelatedGuidelines) (explains table format and definitions) |
| 80 | + |
| 81 | +<table> <tbody> <tr> <th> Taxonomy </th> <th> Taxonomy item </th> <th> Relationship </th> </tr> <tr> <td> <a> CERT C Secure Coding Standard </a> </td> <td> <a> EXP05-C. Do not cast away a const qualification </a> </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> <tr> <td> <a> CERT C Secure Coding Standard </a> </td> <td> <a> STR30-C. Do not attempt to modify string literals </a> </td> <td> Prior to 2018-01-12: CERT: Unspecified Relationship </td> </tr> </tbody> </table> |
| 82 | + |
| 83 | + |
| 84 | +## Bibliography |
| 85 | + |
| 86 | +<table> <tbody> <tr> <td> \[ <a> ISO/IEC 9899:2011 </a> \] </td> <td> Subclause 6.7.3, "Type Qualifiers" </td> </tr> </tbody> </table> |
| 87 | + |
| 88 | + |
| 89 | +## Implementation notes |
| 90 | + |
| 91 | +The implementation does not consider pointer aliasing via multiple indirection. |
| 92 | + |
| 93 | +## References |
| 94 | + |
| 95 | +* CERT-C: [EXP40-C: Do not modify constant objects](https://wiki.sei.cmu.edu/confluence/display/c) |
0 commit comments