You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 75 Next »

Do not cast away a const qualification on a variable type. Casting away the const qualification allows a program to modify a constant value, which results in undefined behavior.

As an illustration, C99 provides a footnote:

The implementation may place a const object that is not volatile in a read-only region of storage. Moreover, the implementation need not allocate storage for such an object if its address is never used.

Non-Compliant Code Example

The remove_spaces() function in this non-compliant code example accepts a pointer to a string str and a string length slen and removes the space character from the string by shifting the remaining characters towards the front of the string. The function remove_spaces() is passed a const char pointer as an argument. The const qualification is cast away and then the contents of the string are modified.

void remove_spaces(char const *str, size_t slen) {
  char *p = (char *)str;
  size_t i;
  for (i = 0; i < slen && str[i]; i++) {
    if (str[i] != ' ') *p++ = str[i];
  }
  *p = '\0';
}

Compliant Solution

In this compliant solution, the function remove_spaces() 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 remove_spaces(char *str, size_t slen) {
  char *p = str;
  size_t i;
  for (i = 0; i < slen && str[i]; i++) {
    if (str[i] != ' ') *p++ = str[i];
  }
  *p = '\0';
}

Non-Compliant Code Example

In this non-compliant code example, the contents of the const int array vals are cleared by the call to memset().

const int vals[3] = {3, 4, 5};
memset(vals, 0, sizeof(vals));

Because the memset() function takes a (non-const) pointer to void, the compiler must implicitly cast away const.

Implementation Details

The compiler GCC issues a warning when an implicit cast is performed.

Compliant Solution

If the intention is to allow the array values to be modified, do not declare the array as const.

int vals[3] = {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);
}

/* ... */
char const INVFNAME[]  = "Invalid file name.";
audit_log((char *)INVFNAME); /* EXP05-EX1 */
/* ... */

Automated Checking

The tool Compass / ROSE should be able to detect explicit casting away of a const object. So it should catch the first NCCE, which does just this.

ROSE should also be able to detect implicit casting away of a const pointer to memset(), and to any other functions that take pointer arguments. To do this, it simply takes any function that is accepting a const pointer as argument, and view the function declaration (which will be available in the AST). So ROSE should be able to catch any const-casts, explicit or implicit.

ROSE won't be able to identify 'legitimate' const casts as specified in EXP05:EX1.

In C++, there is a const_cast keyword specifically representing the casting away of const. My feeling would be that Rose should report const casts using the old syntax, but remain quiet on casts using the const_cast keyword. This is mainly because const_cast is explicitly meant to violate this rule and is easy to search for, while C-style casts may or may not violate this rule, and in general are very difficult to spot.

Risk Assessment

If the object is constant, the compiler may allocate storage in ROM or write-protected memory. Attempting to modify such an object may lead to a program crash or denial-of-service attack.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

EXP05-A

medium

probable

medium

P8

L2

Automated Detection

The LDRA tool suite V 7.6.0 can detect violations of this recommendation.

Compass/ROSE can detect violations of this recommendation.

Related Vulnerabilities

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

References

[[ISO/IEC 9899:1999]] Section 6.7.3, "Type qualifiers"
[[ISO/IEC PDTR 24772]] "HFC Pointer casting and pointer type changes" and "IHN Type system"
[[MISRA 04]] Rule 11.5


EXP04-C. Do not perform byte-by-byte comparisons between structures      03. Expressions (EXP)       EXP06-A. Operands to the sizeof operator should not contain side effects

  • No labels