The std::string
index operators const_reference operator[](size_type) const
and reference operator[](size_type)
return the character stored at the specified position, pos
. When pos >= size()
, 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[]()
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.
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 behavior.
#include <string> extern std::size_t get_index(); void f() { std::string s("01234567"); s[get_index()] = '1'; } |
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::out_of_range
exception if pos >= size().
#include <stdexcept> #include <string> extern std::size_t get_index(); void f() { std::string s("01234567"); try { s.at(get_index()) = '1'; } catch (std::out_of_range &) { // Handle error } } |
This compliant solution checks that the value returned by get_index()
is within a valid range before calling operator[]().
#include <string> extern std::size_t get_index(); void f() { std::string s("01234567"); std::size_t i = get_index(); if (i < s.length()) { s[i] = '1'; } else { // Handle error } } |
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.
#include <string> #include <locale> void capitalize(std::string &s) { std::locale loc; s.front() = std::use_facet<std::ctype<char>>(loc).toupper(s.front()); } |
In this compliant solution, the call to std::string::front()
is made only if the string is not empty.
#include <string> #include <locale> void capitalize(std::string &s) { if (s.empty()) { return; } std::locale loc; s.front() = std::use_facet<std::ctype<char>>(loc).toupper(s.front()); } |
Unchecked element access can lead to out-of-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-CPP | High | Unlikely | Medium | P6 | L2 |
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. |
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
SEI CERT C++ Coding Standard | CTR50-CPP. Guarantee that container indices and iterators are within the valid range |
[ISO/IEC 14882-2014] | Subclause 21.4.5, " |
[Seacord 2013] | Chapter 2, "Strings" |