Rule A5-2-5 (required, implementation, automated)
An array or container shall not be accessed beyond its range.
Rationale
To avoid undefined behavior, range checks should be coded to ensure that container access via iterator arithmetic or subscript operator is within defined bounds. This could also be achieved by accessing an array via a subscript operator with constant indices only. When copying data via standard library algorithms (such as std::copy or std::transform), the target destination must be guaranteed to be large enough to hold the data. Note: This rule applies to C-style arrays and all other containers (including std::basic_string) that access their elements via iterators or via an index. The term iterator includes pointers. Note: Calculating an iterator one past the last element of the array is well defined, but dereferencing such an iterator is not.
Example
// $Id: A5-2-5.cpp 289436 2017-10-04 10:45:23Z michal.szczepankiewicz $
#include <array>
#include <cstdint>
#include <iostream>
void Fn1() noexcept
{
constexpr std::int32_t arraySize = 16;
std::int32_t array[arraySize]{0};
std::int32_t elem1 =
array[0]; // Compliant - access with constant literal that
// is less than ArraySize
std::int32_t elem2 =
array[12]; // Compliant - access with constant literal that
// is less than ArraySize
for (std::int32_t idx = 0; idx < 20; ++idx)
{
std::int32_t elem3 =
array[idx]; // Non-compliant
- access beyond
// bounds, which
has 16 elements
}
ArraySize
std::int32_t shift = 25;
std::int32_t elem4 =
*(array + shift); // Non-compliant - access beyond ArraySize bounds
std::int32_t index = 0;
std::cin >> index;
std::int32_t elem5 =
array[index]; // Non-compliant - index may exceed the ArraySize bounds
if (index < arraySize)
{
std::int32_t elem6 = array[index]; // Compliant - range check coded
}
}
void Fn2() noexcept
{
constexpr std::int32_t arraySize = 32;
std::array<std::int32_t, arraySize> array;
array.fill(0);
std::int32_t elem1 =
array[10]; // Compliant - access with constant literal that
// is less than ArraySize
std::int32_t index = 40;
std::int32_t elem2 =
array[index]; // Non-compliant - access beyond ArraySize bounds
try
{
std::int32_t elem3 =
array.at(50); // Compliant - at() method provides a
// range check, throwing an
exception if
// input exceeds the bounds
}
catch (std::out_of_range&)
{
// Handle an error
}
for (auto&& e : array) // The std::array provides a possibility to iterate
// over its elements with range-based loop
{
// Iterate over all elements
}
}
See also
HIC++ v4.0 [9]: 5.2.1: Ensure that pointer or array access is demonstrably within bounds of a valid object.