STR30-C. Do not attempt to modify string literals
According to the C Standard, 6.4.5, paragraph 3 [ ISO/IEC 9899:2024 ]:
A character string literal is a sequence of zero or more multibyte characters enclosed in double-quotes, as in "xyz" . A UTF-8 string literal is the same, except prefixed by u8 . A wchar _ t string literal is the same, except prefixed by L . A UTF-16 string literal is the same, except prefixed by u . A UTF-32 string literal is the same, except prefixed by U . Collectively, wchar _ t , UTF-16, and UTF-32 string literals are called wide string literals .
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 terminating null character. String literals are usually referred to by a pointer to (or array of) characters. Ideally, they should be assigned only to pointers to (or arrays of) const char or const wchar_t . It is unspecified whether these arrays of string literals are distinct from each other. The behavior is undefined if a program attempts to modify any portion of a string literal. Modifying a string literal frequently results in an access violation because string literals are typically stored in read-only memory. (See undefined behavior 32 .)
Avoid assigning a string literal to a pointer to non- const or casting a string literal to a pointer to non- const . For the purposes of this rule, a pointer to (or array of) const characters must be treated as a string literal. Similarly, the returned value of the following library functions must be treated as a string literal if the first argument is a string literal:
strpbrk(), strchr(), strrchr(), strstr()-wcspbrk(), wcschr(), wcsrchr () , wcsstr()-memchr(), wmemchr()
This rule is a specific instance of EXP40-C. Do not modify constant objects .
Noncompliant Code Example
In this noncompliant code example, the char pointer str is initialized to the address of a string literal. Attempting to modify the string literal is undefined behavior 32 :
char *str = "string literal";
str[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 STR11-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 str . The string stored in str can be modified safely.
char str[] = "string literal";
str[0] = 'S';
Noncompliant Code Example (POSIX)
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:
#include <stdlib.h>
void func(void) {
mkstemp("/tmp/edXXXXXX");
}
The behavior of mkstemp() is described in more detail in FIO21-C. Do not create temporary files in shared directories .
Compliant Solution (POSIX)
This compliant solution uses a named array instead of passing a string literal:
#include <stdlib.h>
void func(void) {
static char fname[] = "/tmp/edXXXXXX";
mkstemp(fname);
}
Noncompliant Code Example (Result of strrchr() )
In this noncompliant example, the char * result of the strrchr() function is used to modify the object pointed to by pathname . Because the argument to strrchr() points to a string literal, the effects of the modification are undefined.
#include <stdio.h>
#include <string.h>
const char *get_dirname(const char *pathname) {
char *slash;
slash = strrchr(pathname, '/');
if (slash) {
*slash = '\0'; /* Undefined behavior */
}
return pathname;
}
int main(void) {
puts(get_dirname(__FILE__));
return 0;
}
Compliant Solution (Result of strrchr() )
This 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 to callers of get_dirname() , a buffer and length for the directory name are passed into the function. It is insufficient to change pathname to require a char * instead of a const char * because conforming compilers are not required to diagnose passing a string literal to a function accepting a char * .
#include <stddef.h>
#include <stdio.h>
#include <string.h>
char *get_dirname(const char *pathname, char *dirname, size_t size) {
const char *slash;
slash = strrchr(pathname, '/');
if (slash) {
ptrdiff_t slash_idx = slash - pathname;
if ((size_t)slash_idx < size) {
memcpy(dirname, pathname, slash_idx);
dirname[slash_idx] = '\0';
return dirname;
}
}
return 0;
}
int main(void) {
char dirname[260];
if (get_dirname(__FILE__, dirname, sizeof(dirname))) {
puts(dirname);
}
return 0;
}
Risk Assessment
Modifying string literals can lead to abnormal program termination and possibly denial-of-service attacks .
| Rule | Severity | Likelihood | Detectable | Repairable | Priority | Level |
|---|---|---|---|---|---|---|
| STR30-C | Low | Likely | No | Yes | P6 | L2 |
Automated Detection
Tool | Version | Checker | Description |
|---|---|---|---|
| Astrée | 25.10 | string-literal-modfication write-to-string-literal | Fully checked |
| Axivion Bauhaus Suite | 7.2.0 | CertC-STR30 | Fully implemented |
| Compass/ROSE | Can detect simple violations of this rule | ||
| Coverity | 2017.07 | PW | Deprecates conversion from a string literal to "char *" |
| Cppcheck Premium | 24.11.0 | premium-cert-str30-c | |
| Helix QAC | 2025.2 | C0556, C0752, C0753, C0754 C++3063, C++3064, C++3605, C++3606, C++3607 | |
2025.2 | CERT.STR.ARG.CONST_TO_NONCONST | ||
| LDRA tool suite | 9.7.1 | 157 S | Partially implemented |
| Parasoft C/C++test | 2025.2 | CERT_C-STR30-a | A string literal shall not be modified |
| PC-lint Plus | 1.4 | 489, 1776 | Partially supported |
| Polyspace Bug Finder | R2025b | CERT C: Rule STR30-C | Checks for writing to const qualified object (rule fully covered) |
| PVS-Studio | 7.42 | V675 | |
| RuleChecker | 25.10 | string-literal-modfication | Partially checked |
| Splint | 3.1.1 | ||
| TrustInSoft Analyzer | 1.38 | mem_access | Exhaustively verified (see one compliant and one non-compliant example ). |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website .
Related Guidelines
Key here (explains table format and definitions)
| Taxonomy | Taxonomy item | Relationship |
| CERT C Secure Coding Standard | EXP05-C. Do not cast away a const qualification | Prior to 2018-01-12: CERT: Unspecified Relationship |
| CERT C Secure Coding Standard | STR11-C. Do not specify the bound of a character array initialized with a string literal | Prior to 2018-01-12: CERT: Unspecified Relationship |
| ISO/IEC TS 17961:2013 | Modifying string literals [strmod] | Prior to 2018-01-12: CERT: Unspecified Relationship |
Bibliography
| [ ISO/IEC 9899:2024 ] | 6.4.5, "String Literals" |
| [ Plum 1991 ] | Topic 1.26, "Strings—String Literals" |
| [ Summit 1995 ] | comp.lang.c FAQ List, Question 1.32 |


