...
In this compliant solution, the parameter pos is declared as size_t, which prevents passing the passing of negative arguments (see INT01-CPP. Use rsize_t or size_t for all integer values representing the size of an object).
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <cstddef>
void insert_in_table(int *table, std::size_t tableSize, std::size_t pos, int value) {
if (pos >= tableSize) {
// Handle error
return;
}
table[pos] = value;
} |
...
In this noncompliant code example, a std::vector is used in place of a pointer and size pair. The function performs a range check to ensure that pos does not exceed the upper bound of the container. Because pos is declared as a (signed) long long, this parameter can assume a negative value. On systems where std::vector::size_type is ultimately implemented as an unsigned int (such as with Microsoft Visual Studio 2013), the usual arithmetic conversions applied for the comparison expression will convert the unsigned value to a signed value. If pos has a negative value, this comparison will not fail, resulting in a write outside the bounds of the std::vector object when the negative value is interpreted as a large unsigned value in the indexing operator.
...
In this compliant solution, the parameter pos is declared as size_t, which ensures that the comparison expression will fail when a large, positive value (converted from a negative argument) is given:.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <vector>
void insert_in_table(std::vector<int> &table, std::size_t pos, int value) {
if (pos >= table.size()) {
// Handle error
return;
}
table[pos] = value;
}
|
...
In this noncompliant code example, it is possible that the the f_imp() function is given a valid iterator but that the iterator is not within the (correct) ending iterator e for a container, and b is an iterator from the same container. However, it is possible that b is not within the valid range of its container. For instance, if f() were called with iterators obtained from an empty container, the end() iterator could be if the container were empty, b would equal e and be improperly dereferenced.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <iterator>
template <typename ForwardIterator>
void f_imp(ForwardIterator b, ForwardIterator e, int val, std::forward_iterator_tag) {
do {
*b++ = val;
} while (b != e);
}
template <typename ForwardIterator>
void f(ForwardIterator b, ForwardIterator e, int val) {
typename std::iterator_traits<ForwardIterator>::iterator_category cat;
f_imp(b, e, val, cat);
} |
...
This compliant solution tests for iterator validity before attempting to dereference the forward iterator: b.
| Code Block | ||||
|---|---|---|---|---|
| ||||
#include <iterator>
template <typename ForwardIterator>
void f_imp(ForwardIterator b, ForwardIterator e, int val, std::forward_iterator_tag) {
while (b != e) {
*b++ = val;
}
}
template <typename ForwardIterator>
void f(ForwardIterator b, ForwardIterator e, int val) {
typename std::iterator_traits<ForwardIterator>::iterator_category cat;
f_imp(b, e, val, cat);
} |
...
Using an invalid array or container index can result in an arbitrary memory overwrite or abnormal program termination.
Rule | Severity | Likelihood | Detectable |
|---|
Repairable | Priority | Level |
|---|---|---|
CTR50-CPP | High | Likely |
No | No | P9 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Astrée |
| overflow_upon_dereference | |||||||
| CodeSonar |
| LANG.MEM.BO | Buffer overrun | ||||||
| Helix QAC |
| C++3139, C++3140 DF2891 | |||||||
| Klocwork |
| ABV.ANY_SIZE_ARRAY | |||||||
| LDRA tool suite |
| 45 D, 47 S, 476 S, 489 S, 64 X, 66 X, 68 X, 69 X, 70 X, 71 X, 79 X | Partially implemented | ||||||
| Parasoft C/C++test |
| CERT_CPP-CTR50-a | Guarantee that container indices are within the valid range | |||||||
| Polyspace Bug Finder |
| CERT C++: CTR50-CPP | Checks for:
Rule partially covered. | ||||||
| PVS-Studio |
| V781 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
| SEI CERT C Coding Standard | ARR30-C. Do not form or use out-of-bounds pointers or array subscripts |
| MITRE CWE | CWE 119, Failure to Constrain Operations within the Bounds of a Memory Buffer CWE 129, Improper Validation of Array Index |
Bibliography
| [ISO/IEC 14882-2014] | Clause 23, "Containers Library" |
| [ISO/IEC TR 24772-2013] | Boundary Beginning Violation [XYX] Wrap- |
| Around Error [XYY] Unchecked Array Indexing [XYZ] |
| [Viega |
| 2005] | Section 5.2.13, "Unchecked Array Indexing" |
...
...