The std::basic_string template class has unusual invalidation semantics. According to the C++ Standard, [string.require], paragraph 5 [ISO/IEC 14882-2014]:
References, pointers, and iterators referring to the elements of a
basic_stringsequence may be invalidated by the following uses of thatbasic_stringobject:
- As an argument to any standard library function taking a reference to non-const
basic_stringas an argument.- Calling non-const member functions, except
operator[],at,front,back,begin,rbegin,end, andrend.
Examples of standard library functions taking a reference to non-const std::basic_string are std::swap(), ::operator>>(basic_istream &, string &), and std::getline().
Do not use an invalidated reference, pointer, or iterator because doing so results in undefined behavior.
This rule is a specific instance of CTR51-CPP. Use valid references, pointers, and iterators to reference elements of a container.
Noncompliant Code Example
This noncompliant code example copies input into a std::string, replacing semicolon (;) characters with spaces. This example is noncompliant because the iterator loc is invalidated after the first call to insert(). The behavior of subsequent calls to insert() is undefined.
#include <string>
void f(const std::string &input) {
std::string email;
// Copy input into email converting ";" to " "
std::string::iterator loc = email.begin();
for (auto I = input.begin(), E = input.end(); I != E; ++I, ++loc) {
email.insert(loc, *I != ';' ? *I : ' ');
}
}
Compliant Solution (std::string::insert())
In this compliant solution, the value of the iterator loc is updated as a result of each call to insert() so that the invalidated iterator is never accessed. The updated iterator is then incremented at the end of the loop.
#include <string>
void f(const std::string &input) {
std::string email;
// Copy input into email converting ";" to " "
std::string::iterator loc = email.begin();
for (auto I = input.begin(), E = input.end(); I != E; ++I, ++loc) {
loc = email.insert(loc, *I != ';' ? *I : ' ');
}
}
Compliant Solution (std::replace())
This compliant solution uses a standard algorithm to perform the replacement. When possible, using a generic algorithm is preferable to inventing your own solution.
#include <algorithm>
#include <string>
void f(const std::string &input) {
std::string email{input};
std::replace(email.begin(), email.end(), ';', ' ');
}
Risk Assessment
Using an invalid reference, pointer, or iterator to a string object could allow an attacker to run arbitrary code.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
|---|---|---|---|---|---|
STR52-CPP | High | Probable | High | P6 | L2 |
Automated Detection
Tool | Version | Checker | Description |
|---|---|---|---|
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
| SEI CERT C++ Coding Standard | CTR51-CPP. Use valid references, pointers, and iterators to reference elements of a container |
Bibliography
| [ISO/IEC 14882-2014] | Subclause 21.4.1, " |
| [Meyers 01] | Item 43, "Prefer Algorithm Calls to Hand-written Loops" |


