CertC++-CTR53

Use valid iterator ranges

Required inputs: IR

When iterating over elements of a container, the iterators used must iterate over a valid range. An iterator range is a pair of iterators that refer to the first and past-the-end elements of the range respectively.

A valid iterator range has all of the following characteristics:

An empty iterator range (where the two iterators are valid and equivalent) is considered to be valid.

Using a range of two iterators that are invalidated or do not refer into the same container results in undefined behavior.

Noncompliant Code Example

In this noncompliant example, the two iterators that delimit the range point into the same container, but the first iterator does not precede the second. On each iteration of its internal loop,  std::for_each() compares the first iterator (after incrementing it) with the second for equality; as long as they are not equal, it will continue to increment the first iterator. Incrementing the iterator representing the past-the-end element of the range results in undefined behavior.

#include <algorithm>
#include <iostream>
#include <vector>
 
void f(const std::vector<int> &c) {
  std::for_each(c.end(), c.begin(), [](int i) { std::cout << i; });
}

Invalid iterator ranges can also result from comparison functions that return true for equal values. See  CTR57-CPP. Provide a valid ordering predicate for more information about comparators.

Compliant Solution

In this compliant solution, the iterator values passed to  std::for_each() are passed in the proper order.

#include <algorithm>
#include <iostream>
#include <vector>

void f(const std::vector<int> &c) {
  std::for_each(c.begin(), c.end(), [](int i) { std::cout << i; });
}
Noncompliant Code Example

In this noncompliant code example, iterators from different containers are passed for the same iterator range. Although many STL implementations will compile this code and the program may behave as the developer expects, there is no requirement that an STL implementation treat a default-initialized iterator as a synonym for the iterator returned by  end().

#include <algorithm>
#include <iostream>
#include <vector>

void f(const std::vector<int> &c) {
  std::vector<int>::const_iterator e;
  std::for_each(c.begin(), e, [](int i) { std::cout << i; });
}
Compliant Solution

In this compliant solution, the proper iterator generated by a call to end() is passed.

#include <algorithm>
#include <iostream>
#include <vector>

void f(const std::vector<int> &c) {
  std::for_each(c.begin(), c.end(), [](int i) { std::cout << i; });
}
Risk Assessment

Using an invalid iterator range is similar to allowing a buffer overflow, which can lead to an attacker running arbitrary code.

Rule Severity Likelihood Remediation Cost Priority Level
CTR53-CPP High Probable High P6 L2
Related Guidelines
SEI CERT C++ Coding Standard CTR51-CPP. Use valid references, pointers, and iterators to reference elements of a container
CTR57-CPP. Provide a valid ordering predicate
Bibliography
[ ISO/IEC 14882-2014] Clause 24, "Iterators Library"
Subclause 25.3, "Mutating Sequence Operations" 
[ Meyers 2001] Item 32, "Follow Remove-Like Algorithms with erase If You Really Want to Remove Something"
Excerpt from SEI CERT C++ Coding Standard [https://cmu-sei.github.io/secure-coding-standards/sei-cert-cpp-coding-standard/rules/containers-ctr/ctr53-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

different_iterators_containers

Iterators for parameter ‘{}’ and parameter ‘{}’ come from different containers.

None

False

iterator_might_not_initialized

Not all paths initialize iterator ‘{}’ for parameter ‘{}’.

None

False

iterator_not_initialized

Iterator ‘{}’ for parameter ‘{}’ is not initialized.

None

False

possible_different_iterators_containers

Iterators for parameter ‘{}’ and parameter ‘{}’ come possibly from different containers.

None

False

possible_reversed_iterators

Possibly invalid {} for parameter ‘{}’.

None

False

reversed_iterators

Invalid {} for parameter ‘{}’.

None

False

Options

begin_parameter_member_function_names

begin_parameter_member_function_names : set[str] = {'begin', 'cbegin', 'constBegin', 'crbegin', 'rbegin'}

Function names that indication the start of a range.
 

end_parameter_member_function_names

end_parameter_member_function_names : set[str] = {'cend', 'constEnd', 'crend', 'end', 'rend'}

Function names that indication the end of a range.
 

functions

functions

Type: dict[bauhaus.analysis.config.QualifiedName, tuple]

Default:

{
   'std::copy': (0, 1),
   'std::copy_backwards': (0, 1),
   'std::copy_if': (0, 1),
   'std::for_each': (0, 1),
   'std::move': (0, 1),
   'std::move_backward': (0, 1),
   'std::partition_copy': (0, 1),
   'std::remove_copy': (0, 1),
   'std::remove_copy_if': (0, 1),
   'std::replace_copy': (0, 1),
   'std::replace_copy_if': (0, 1),
   'std::rotate_copy': (0, 2),
   'std::transform': (0, 1),
   'std::unique_copy': (0, 1),
   'std::vector::insert': (2, 3)
}
Table of functions with unchecked output iterator(s).