A string literal is a sequence of zero or more multibyte characters enclosed in double quotes (for example, "xyz"
). A wide string literal is the same, except prefixed by the letter 'L'
(for example, L"xyz"
).
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 because string literals are typically stored in read-only memory. See also undefined behavior 33 of Annex J of the C Standard [ISO/IEC 9899:2011].
The returned value of the library functions strpbrk()
, strchr()
, strrchr()
, wcspbrk()
, wcschr()
, and wcsrchr()
and pointer to (or array of) const
characters shall be treated as a string literal.
Do not attempt to modify a string literal. Use a named array of characters to obtain a modifiable string.
Noncompliant Code Example
In this noncompliant code example, the char
pointer p
is initialized to the address of a string literal. Attempting to modify the string literal results in undefined behavior.
char *p = "string literal"; p[0] = 'S';
Compliant Solution
As an array initializer, a string literal specifies the initial values of characters in an array as well as the size of the array. (See STR36-C. Do not specify the bound of a character array initialized with a string literal.) This code creates a copy of the string literal in the space allocated to the character array a
. The string stored in a
can be safely modified.
char a[] = "string literal"; a[0] = 'S';
Noncompliant Code Example
In this noncompliant code example, a string literal is passed to the (pointer to non-const
) parameter of the POSIX function mkstemp()
, which then modifies the characters of the string literal.
char *fname; fname = mkstemp("/tmp/edXXXXXX");
Compliant Solution
Instead of passing a string literal, use a named array:
static char fname[] = "/tmp/edXXXXXX"; mkstemp(fname);
Noncompliant Code Example (Result of strrchr()
)
In this noncompliant example, the non-const
char*
result of the strrchr()
function is used to modify the object pointed to by pathname
. Because 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.
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. Although converting a string literal to non-const
char*
is permitted by the language, conforming compilers could issue a diagnostic for such code. See also EXP05-C. Do not cast away a const qualification.
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.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
STR30-C | low | likely | low | P9 | L2 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
Compass/ROSE | Can detect simple violations of this rule. | ||
9.7.1 | 157 S | Partially implemented. | |
PRQA QA-C | Unable to render {include} The included page could not be found. | 0556 | Partially implemented. |
Splint | 3.1.1 |
|
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
CERT C++ Secure Coding Standard | STR30-CPP. Do not attempt to modify string literals |
ISO/IEC TR 17961 | (Draft) Modifying string literals [strmod] |
Bibliography
[Summit 1995] | comp.lang.c FAQ list, Question 1.32 |
[Plum 1991] | Topic 1.26, "Strings—String Literals" |