Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Referenced Annex J, EXP05-C, and added an example.

...

At compile time, string literals are used to create an array of static storage duration of sufficient length to contain the character sequence and a null-termination character. It is unspecified whether these arrays are distinct. The behavior is undefined if a program attempts to modify string literals but frequently results in an access violation, as string literals are typically stored in read-only memory. See also undefined behavior 30 of Annex J of C99.

Do not attempt to modify a string literal. Use a named array of characters to obtain a modifiable string.

...

In this noncompliant example, the mktemp() function modifies its string argument.

Code Block
bgColor#FFcccc

char *fname;
fname = mktemp("/tmp/edXXXXXX");

Compliant Solution

...

Code Block
bgColor#ccccff
static char fname[] = "/tmp/edXXXXXX";

mktemp(fname);

Noncompliant Code Example (Result of strrchr())

In this noncompliant example, the non-const char* result of the strchr() function is used to modify the object pointed to by pathname. Since the pointer points to a string literal the effects of the modification are undefined and are likely to cause a signal such as SIGSEGV to be generated for the process if the object is stored in read-only memory.

Code Block
bgColor#FFcccc

const char* get_dirname(const char* pathname) {
  char* slash;
  slash = strrchr(pathname, '/');
  if (slash)
    *slash = '\0'; /* undefined behavior */
  return pathname;
}

int main() {
  puts(get_dirname(__FILE__));
  return 0;
}

Compliant Solution (Result of strrchr())

A compliant solution avoids modifying a const object even if it is possible to obtain a non-const pointer to such an object by calling a standard C library function such as strrchr(). To reduce the risk of callers of get_dirname() passing constant objects to the function the argument is declared to be a non-const pointer. While converting a string literal to non-const char* is permitted by the language conforming compilers may issue a diagnostic for such code. See also EXP05-C. Do not cast away a const qualification.

Code Block
bgColor#ccccff

char* get_dirname(char* pathname) {
  char* slash;
  slash = strrchr(pathname, '/');
  if (slash)
    *slash = '\0';
  return pathname;
}

int main() {
  char pathname[] = __FILE__;
  /* calling get_dirname(__FILE__) may be diagnosed */
  puts(get_dirname(pathname));
  return 0;
}

Risk Assessment

Modifying string literals can lead to abnormal program termination and possibly denial-of-service attacks.

...