CertC++-STR53¶
Range check element access
Required inputs: IR
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.
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
behavior.
#include <string>
extern std::size_t get_index();
void f() {
std::string s("01234567");
s[get_index()] = '1';
}
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::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
}
}
Compliant Solution (Range Check)
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
}
}
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.
#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.
#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());
}
Risk Assessment
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 |
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, "
basic_string Element Access"
|
| [ Seacord 2013] | Chapter 2, "Strings" |
Possible Messages
Key |
Text |
Severity |
Disabled |
|---|---|---|---|
range_check_back_front_method |
No range check before calling {} method |
None |
False |
range_check_bracket_operator |
No range check before using bracket operator. |
None |
False |
Options¶
This rule shares the following common options: exclude_in_macros, exclude_messages_in_system_headers, excludes, extend_exclude_to_macro_invocations, includes, justification_checker, languages, post_processing, provider, report_at, severity
The following places define options that affect this rule: Stylechecks, Analysis-GlobalOptions
string_range_access_functions¶
string_range_access_functions
Set of functions that unconditionally accesses the character buffer.Type: set[bauhaus.analysis.config.QualifiedName]
Default:
{'std::basic_string::at', 'std::basic_string::back', 'std::basic_string::front', 'std::basic_string::operator[]'}
string_size_verification_functions¶
string_size_verification_functions
Functions in this set are treated as basic checks for a valid character buffer.Type: set[bauhaus.analysis.config.QualifiedName]
Default:
{'std::basic_string::empty', 'std::basic_string::length', 'std::basic_string::reserve', 'std::basic_string::resize', 'std::basic_string::swap'}
trace_non_local_strings¶
trace_non_local_strings : bool = False