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"
Excerpt from SEI CERT C++ Coding Standard [https://cmu-sei.github.io/secure-coding-standards/sei-cert-cpp-coding-standard/rules/characters-and-strings-str/str53-cpp], Copyright (C) 1995-2026 Carnegie Mellon University. See section 9.4. "3rd-Party Licenses" in the documentation for full details.

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

string_range_access_functions

string_range_access_functions

Type: set[bauhaus.analysis.config.QualifiedName]

Default: {'std::basic_string::at', 'std::basic_string::back', 'std::basic_string::front', 'std::basic_string::operator[]'}

Set of functions that unconditionally accesses the character buffer.
 

string_size_verification_functions

string_size_verification_functions

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'}

Functions in this set are treated as basic checks for a valid character buffer.
 

trace_non_local_strings

trace_non_local_strings : bool = False

Whether strings from function parameters or member fields should be inspected.