Do not attempt to modify an object declared as const
. The specification of const
in variables and parameters implies to a maintainer or caller that, despite knowing some memory location, the code will not modify its content. Although C++ allows you to remove the specifier using typecasts, doing so violates the implication of the specifier.
Non-Compliant Code Example
In this example, the function f()
is passed a const
char
pointer. It then typecasts the const
specification away and proceeds to modify the contents.
void f(char const *str, int slen) { char *p = const_cast<char*>(str); int i; for (i = 0; i < slen && str[i]; i++) { if (str[i] != ' ') *p++ = str[i]; } }
Compliant Solution
In this compliant solution, the function f
is passed a non-const
char
pointer. The calling function must ensure that the null-terminated byte string passed to the function is not const
by making a copy of the string or by other means.
void f(char *str, int slen) { char *p = str; int i; for (i = 0; i < slen && str[i]; i++) { if (str[i] != ' ') *p++ = str[i]; } }
Non-Compliant Code Example
In this example, a const
int
array vals
is declared, and then its content is modified by calling memset
with the function, leading to values of 0 in the vals
array.
int const vals[] = {3, 4, 5}; memset((int*) vals, 0, sizeof(vals));
Compliant Solution
If the intention is to allow the array values to be modified, do not declare the array as const
.
int vals[] = {3, 4, 5}; memset(vals, 0, sizeof(vals));
Otherwise, do not attempt to modify the contents of the array.
Exceptions
EXP05-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. For example, the following code casts away the const
qualification of INVFNAME
in the call to the audit_log()
function.
/* Legacy function defined elsewhere - cannot be modified */ void audit_log(char *errstr) { fprintf(stderr, "Error: %s.\n", errstr); } /* ... */ const char INVFNAME[] = "Invalid file name."; audit_log(const_cast<char*>(INVFNAME)); /* EXP05-EX1 */ /* ... */
Risk Assessment
If the object really is constant, the compiler may have put it in ROM or write-protected memory. Trying to modify such an object may lead to a program crash. This could allow an attacker to mount a denial-of-service attack.
Recommendation |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
EXP35-CPP |
medium |
probable |
medium |
P8 |
L2 |
Automated Detection
The LDRA tool suite V 7.6.0 can detect violations of this recommendation.
GCC Compiler can detect violations of this rule when the -Wcast-qual
flag is used.
Compass/ROSE can detect violations of this recommendation.
Tool |
Version |
Checker |
Description |
---|---|---|---|
LDRA tool suite |
7.6.0 |
|
|
GCC |
|
|
Can detect violations of this recommendation when the |
Compass/ROSE |
|
|
|
ECLAIR |
1.2 | castexpr |
Fully Implemented |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Other Languages
This rule appears in the C Secure Coding Standard as EXP05-C. Do not cast away a const qualification.
Bibliography
[ISO/IEC 14882-2003] Sections 3.9.3 CV-qualifiers and 3.10 Lvalues and rvalues (para. 13).
[Sutter 04] Item 94: Avoid casting away const.
EXP34-CPP. Ensure a null pointer is not dereferenced 03. Expressions (EXP) EXP36-CPP. Do not convert pointers into more strictly aligned pointer types