Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: REM Cost Reform

Wiki MarkupDo not cast away a {{const}} qualification on a variable on an object of pointer type. Casting away the {{const}} qualification will allow violation of rule \[[EXP31-C|EXP31-C. Do not modify constant values ]\] prohibiting the modification of constant values.

...

qualification allows a program to modify the object referred to by the pointer, which may result in undefined behavior. See undefined behavior 61 in Appendix J of the C Standard.

As an illustration, the C Standard [ISO/IEC 9899:2011] provides a footnote (subclause 6.7.3, paragraph 4):

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.

Noncompliant Code Example

The remove_spaces() function in this noncompliant 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 toward the front of the string. The function remove_spaces() is passed a const char pointer . It then typecasts the as an argument. The const qualification is cast away, and proceeds to modify then the contents of the string are modified.

Code Block
bgColor#FFcccc
langc

void remove_spaces(const char *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.

Code Block
bgColor#ccccff
langc

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';
}

...

Noncompliant Code Example

In this noncompliant code example, a the contents of the const int array vals is declared and its content modified by are cleared by the call to memset() with the function, clearing the contents of the vals array.:

Code Block
bgColor#FFcccc
langc
Code Block

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 GCC compiler 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.:

Code Block
bgColor#ccccff
langc

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

Otherwise, do not attempt to modify the contents of the array.

Exception

Exceptions

EXP05-C-EX1: An exception to this rule recommendation 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.

Code Block
/* 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((char *)INVFNAME); /* EXP05-EX1 */
/* ... */

EXP05-C-EX2: A number of C standard library functions are specified to return non-const pointers that refer to their const-qualified arguments. When the actual arguments to such functions reference const objects, attempting to use the returned non-const pointers to modify the const objects would be a violation of EXP40-C. Do not modify constant objects and would lead to undefined behavior. These functions are the following:

memchr

strchr

strpbrk

strrchr

strstr

strtod

strtof

strtold

strtol

strtoll

strtoul

strtoull

wmemchr

wcschr

wcspbrk

wcsrchr

wcsstr




For instance, in following example, the function strchr returns an unqualified char* that points to the terminating null character of the constant character array s (which could be stored in ROM). Even though the pointer is not const, attempting to modify the character it points to would lead to undefined behavior.

Code Block
  extern const char s[];
  char* where;
  where = strchr(s, '\0');
  /* Modifying *s is undefined */

Similarly, in the following example, the function strtol sets the unqualified char* pointer referenced by end to point just past the last successfully parsed character of the constant character array s (which could be stored in ROM). Even though the pointer is not const, attempting to modify the character it points to would lead to undefined behavior.

Code Block
  extern const char s[];
  long x;
  char* end;
  x = strtol(s, &end, 0);
  /* Modifying **end is undefined */

EXP05-C-EX3: Because const means "read-only," and not "constant," it is sometimes useful to declare struct members as (pointer to) const objects to obtain diagnostics when the user tries to change them in some way other than via the functions that are specifically designed to maintain that data type. Within those functions, however, it may be necessary to strip off the const qualification to update those members.

Risk Assessment

If the object really is constant, the compiler may have put it allocate storage in ROM or write-protected memory. Trying Attempting to modify such an object may lead to a program crash . This could allow an attacker to mount a or denial-of-service attack.

Rule

Recommendation

Severity

Likelihood

Remediation Cost

Detectable

Repairable

Priority

Level

EXP05-C

Medium

Probable

No

No

P4

L3

Automated Detection

Tool

Version

Checker

Description

Astrée
Include Page
Astrée_V
Astrée_V
pointer-qualifier-cast-const
pointer-qualifier-cast-const-implicit
Fully checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC-EXP05Fully implemented
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V
LANG.CAST.PC.CRCQCast removes const qualifier
Compass/ROSE




ECLAIR

Include Page
ECLAIR_V
ECLAIR_V

CC2.EXP05

Fully implemented

GCC
Include Page
GCC_V
GCC_V


Can detect violations of this recommendation when the -Wcast-qual flag is used

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C0311, C0431
LDRA tool suite
Include Page
LDRA_V
LDRA_V

203 S

Fully implemented

Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_C-EXP05-a

A

1 (low)

2 (probable)

2 (medium)

P4

L3

References

...

cast shall not remove any 'const' or 'volatile' qualification from the type of a pointer or reference

PC-lint Plus

Include Page
PC-lint Plus_V
PC-lint Plus_V

9005

Partially supported

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rec. EXP05-C


Checks for cast to pointer that removes const qualification (rec. fully supported)

RuleChecker
Include Page
RuleChecker_V
RuleChecker_V
pointer-qualifier-cast-const
pointer-qualifier-cast-const-implicit
Fully checked

Related Vulnerabilities

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

Related Guidelines

SEI CERT C++ Coding StandardEXP55-CPP. Do not access a cv-qualified object through a cv-unqualified type
ISO/IEC TR 24772:2013Pointer Casting and Pointer Type Changes [HFC]
Type System [IHN]
MISRA C:2012Rule 11.8 (required)
MITRE CWECWE-704, Incorrect type conversion or cast

Bibliography

[ISO/IEC 9899:2011]Subclause 6.7.3, "Type

...

Qualifiers"


...

Image Added Image Added Image Added