...
This non-compliant example copies the null-terminated byte string input into the string email, replacing ';' characters with spaces. This example is non-compliant because the iterator loc is invalidated after the first call to insert(). The behavior of subsequent calls to insert is undefined.
| Code Block | ||||
|---|---|---|---|---|
| ||||
char input[] = "bogus@addr.com; cat /etc/passwd";
string email;
string::iterator loc = email.begin();
// copy into string converting ";" to " "
for (size_t i=0; i <= strlen(input); i++) {
if (input[i] != ';') {
email.insert(loc++, input[i]);
}
else {
email.insert(loc++, ' ');
}
} // end string for each element in NTBS
|
...
In this compliant solution, the value of the iterator loc is updated as a result of each call to insert so that the insert() method is never called with an invalid iterator. The updated iterator is then incremented at the end of the loop.
| Code Block | ||||
|---|---|---|---|---|
| ||||
char input[] = "bogus@addr.com; cat /etc/passwd";
string email;
string::iterator loc = email.begin();
// copy into string converting ";" to " "
for (size_t i=0; i <= strlen(input); i++) {
if (input[i] != ';') {
loc = email.insert(loc, input[i]);
}
else {
loc = email.insert(loc, ' ');
}
++loc;
} // end string for each element in NTBS
|
...
In this non-compliant example, the string s is initialized as "rcs" and the string iterator si is initialized to the beginning of the string. The size of s is three, and we'll assume the capacity is fifteen. The for loop appends 20 characters to the end of the sting. As a result, the si iterator is invalidated because the capacity of the string is exceeded, requiring a reallocation. As a result, the call to insert() results in undefined behavior.
| Code Block | ||||
|---|---|---|---|---|
| ||||
string s("rcs");
string::iterator si = s.begin();
for (size_t i=0; i<20; ++i) {
s.push_back('x');
}
s.insert(si, '*');
|
...
In this compliant solution, the non-compliant example is modified to only append capacity-size characters to the string s. As a result, the call to push_back() no longer invalidates the iterator.
| Code Block | ||||
|---|---|---|---|---|
| ||||
string s("rcs");
string::iterator si = s.begin();
for (size_t i=0; i < 20; ++i) {
if ( s.size() == s.capacity() ) {
break;
}
s.push_back('x');
}
s.insert(si, '*');
|
...