Since std::basic_string
is a container of characters, this rule is a specific instance of CTR51-CPP. Use valid references, pointers, and iterators to reference elements of a container. As a container, it supports iterators just like other containers in the Standard Template Library. However, the std::basic_string
template class has unusual invalidation semantics. The C++ Standard, [string.require], paragraph 5 [ISO/IEC 14882-2014], states the following:
References, pointers, and iterators referring to the elements of a
basic_string
...
sequence may be
...
invalidated by the following uses of that
...
basic_string
...
object:
- As an argument to any standard library function taking a reference to non-const
basic_string
as 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.
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.
Code Block | ||||
---|---|---|---|---|
| ||||
#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.
Code Block | ||||
---|---|---|---|---|
| ||||
#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.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <algorithm>
#include <string>
void f(const std::string &input) {
std::string email{input};
std::replace(email.begin(), email.end(), ';', ' ');
} |
Noncompliant Code Example
In this noncompliant code example, data
is invalidated after the call to replace()
, and so its use in g()
is undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <iostream>
#include <string>
extern void g(const char *);
void f(std::string &exampleString) {
const char *data = exampleString.data();
// ...
exampleString.replace(0, 2, "bb");
// ...
g(data);
} |
Compliant Solution
In this compliant solution, the pointer to exampleString
's internal buffer is not generated until after the modification from replace()
has completed.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <iostream>
#include <string>
extern void g(const char *);
void f(std::string &exampleString) {
// ...
exampleString.replace(0, 2, "bb");
// ...
g(exampleString.data());
} |
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 | ||||||
---|---|---|---|---|---|---|---|---|---|
CodeSonar |
| ALLOC.UAF | Use After Free | ||||||
Helix QAC |
| DF4746, DF4747, DF4748, DF4749 | |||||||
Parasoft C/C++test |
| CERT_CPP-STR52-a | Use valid references, pointers, and iterators to reference elements of a basic_string | ||||||
Polyspace Bug Finder |
| CERT C++: STR52-CPP | Checks for use of invalid string iterator (rule partially covered). |
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 2001] | Item 43, "Prefer Algorithm Calls to Hand-written Loops" |
...