...
The index operators
...
std::string
index operators const_reference
...
operator[](size_type
...
)
...
const
...
and reference
...
operator[](size_type
...
return )
return the character stored at the specified position if , pos < size()
. If When pos >= = size()
, the const
version returns the terminating null character type value. Otherwise, the behavior is undefined.In any case, the behavior of the index operators is a reference to an object of type charT
with value charT()
is returned. The index operators are unchecked (no exceptions are thrown for range errors), and attempting to modify the resulting out-of-range object results in undefined behavior.
Similarly, the std::string::back()
and std::string::front()
functions are unchecked as they are defined to call through to the appropriate operator[]()
.
Non-Compliant Code Example
without throwing.
Do not pass an out-of-range value as an argument to std::string::operator[]()
. Similarly, do not call std::string::back()
or std::string::front()
on an empty string. This rule is a specific instance of CTR50-CPP. Guarantee that container indices and iterators are within the valid range.
Noncompliant Code Example
In this noncompliant code example, the value returned by the call to get_index()
may be greater than the number of elements stored in the string, resulting in undefined behaviorThe behavior of this non-compliant example is undefined because the index i
used to reference bs
may be outside the range of bs
, causing a write-out-of-bounds error.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string> extern std::size_t get_index(); void f() { std::string bss("01234567"); size_t i = f(); bs[i s[get_index()] = '\01'; |
This program does not typically raise an exception and may be exploited to overwrite memory at a specified location.
Compliant Solution
} |
Compliant Solution (try
/catch
)
This compliant solution uses the std::basic_string::at()
function, which behaves in a similar fashion to the index operator[]
but throws a std::
This compliant solution uses the {{basic_string at()}} method, which behaves in a similar fashion to the index {{operator\[\]}} but throws an {{ Wiki Markup out_of_range
}} exception if {{pos
>=
size()
}}.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <stdexcept> #include <string> extern std::size_t get_index(); void f() { std::string bss("01234567"); try { size_t i = f(); bs s.at(iget_index()) = '\01'; } catch (...std::out_of_range &) { cerr << "Index out// ofHandle range"error << endl;} } |
In any case, the behavior of the index operators is unchecked (no exceptions are thrown).
Non-Compliant Code Example
Compliant Solution (Range Check)
This compliant solution checks that the value returned by get_index()
is within a valid range before calling operator[]()
The behavior of this non-compliant example is undefined because the size()
of bs
is 8 but the index used to reference bs
ranges from 0 through 99.
Code Block | |||||
---|---|---|---|---|---|
| |||||
#include <string> extern std::size_t get_index(); void f() { std::string s string bs("01234567"); for (int std::size_t i=0; = get_index(); if (i < 100; i++s.length()) { bs s[i] = '\01'; } else { // Handle error } |
This program does not typically raise an exception and is likely to crash.
Compliant Solution
} |
Noncompliant Code Example
This noncompliant code example attempts to replace the initial character in the string with a capitalized equivalent. However, if the given string is empty, the behavior is undefined.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <string>
#include <locale>
void capitalize(std::string &s) {
std::locale loc;
s.front() = std::use_facet<std::ctype<char>>(loc).toupper(s.front());
} |
Compliant Solution
In this compliant solution, the call to std::string::front()
is made only if the string is not empty.Use the fill algorithm to assign the value '\0'
to evey element in the specified range:
Code Block | ||||
---|---|---|---|---|
| ||||
size_t const max_fill = 100; #include <string> #include <locale> void capitalize(std::string bs("01234567"); fill(bs.begin(), bs.begin()+std::min(max_fill, bs.length()), '\0' ); |
...
&s) {
if (s.empty()) {
return;
}
std::locale loc;
s.front() = std::use_facet<std::ctype<char>>(loc).toupper(s.front());
} |
Risk Assessment
Unchecked element access can lead to out-of-bounds bound reads and writes and write-anywhere exploits. These exploits can, in turn, lead to the execution of arbitrary code with the permissions of the vulnerable process.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|
STR53- |
3 (high)
3 (likely)
1 (high)
P9
L2
Bibliography
Wiki Markup |
---|
\[[Seacord 05|AA. Bibliography#Seacord 05]\] Chapter 2 Strings
\[[ISO/IEC 14882-2003|AA. Bibliography#ISO/IEC 14882-2003]\] Section 21.3.4 basic_string element access |
CPP | High | Unlikely | Medium | P6 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| assert_failure | |||||||
CodeSonar |
| LANG.MEM.BO | Buffer overrun Buffer underrun Tainted buffer access Type overrun Type underrun | ||||||
Helix QAC |
| C++3162, C++3163, C++3164, C++3165 | |||||||
Parasoft C/C++test |
| CERT_CPP-STR53-a | Guarantee that container indices are within the valid range | ||||||
Polyspace Bug Finder |
| CERT C++: STR53-CPP | Checks for:
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 | CTR50-CPP. Guarantee that container indices and iterators are within the valid range |
Bibliography
[ISO/IEC 14882-2014] | Subclause 21.4.5, " |
[Seacord 2013] | Chapter 2, "Strings" |
...
STR38-CPP. Use valid references, pointers, and iterators to reference string objects 07. Characters and Strings (STR) 08. Memory Management (MEM)