原文链接:

CTR55-CPP. Do not use an additive operator on an iterator if the result would overflow

https://wiki.sei.cmu.edu/confluence/display/cplusplus/CTR55-CPP.+Do+not+use+an+additive+operator+on+an+iterator+if+the+result+would+overflow

具有整型的表达式可以与指针相加或相减,结果是指针类型的值。如果结果指针不是一个有效的容器成员,或者在容器最后一个元素之后,加法运算的行为将是 未定义的. C++ 标准, [expr.add], paragraph 5 [ISO/IEC 14882-2014],部分陈述如下:

Expressions that have an integral type can be added to or subtracted from a pointer, resulting in a value of the pointer type. If the resulting pointer is not a valid member of the container, or one past the last element of the container, the behavior of the additive operator is undefined. The C++ Standard, [expr.add], paragraph 5 [ISO/IEC 14882-2014], in part, states the following:

If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.

因为迭代器是一个泛化的指针,同样的限制也会被施加在和任随机访问迭代器的加法运算上。特别地,C++ 标准, [iterator.requirements.general], paragraph 5, 陈述如下:

Because iterators are a generalization of pointers, the same constraints apply to additive operators with random access iterators. Specifically, the C++ Standard, [iterator.requirements.general], paragraph 5, states the following:

Just as a regular pointer to an array guarantees that there is a pointer value pointing past the last element of the array, so for any iterator type there is an iterator value that points past the last element of a corresponding sequence. These values are called past-the-end values. Values of an iterator i for which the expression *i is defined are called dereferenceable. The library never assumes that past-the-end values are dereferenceable.

当运算结果会溢出容器范围时,不允许一个整型地表达式和指针或者随机访问迭代器相加或者相减。

Do not allow an expression of integral type to add to or subtract from a pointer or random access iterator when the resulting value would overflow the bounds of the container.

不合规的代码示例 (std::vector) Noncompliant Code Example (std::vector)

在这个不合规的代码示例中,一个来自 std::vector 的随机访问迭代器被用在一个加法表达式中,但是结果将在容器范围之外,而不是一个尾后值。

In this noncompliant code example, a random access iterator from a std::vector is used in an additive expression, but the resulting value could be outside the bounds of the container rather than a past-the-end value.

1
2
3
4
5
6
7
8
#include <iostream>
#include <vector>

void f(const std::vector<int> &c) {
for (auto i = c.begin(), e = i + 20; i != e; ++i) {
std::cout << *i << std::endl;
}
}

合规方案 (std::vector) Compliant Solution (std::vector)

这个合规方案假设程序员的意图是处理容器中最多 20 项。和假设所有容器有 20 项或者更多元素不同的是,在加法中,容器的尺寸被用来决定容器的上限。

This compliant solution assumes that the programmer’s intention was to process up to 20 items in the container. Instead of assuming all containers will have 20 or more elements, the size of the container is used to determine the upper bound on the addition.

1
2
3
4
5
6
7
8
9
#include <algorithm>
#include <vector>

void f(const std::vector<int> &c) {
const std::vector<int>::size_type maxSize = 20;
for (auto i = c.begin(), e = i + std::min(maxSize, c.size()); i != e; ++i) {
// ...
}
}

风险评估 Risk Assessment

如果在指针上加上或者减去一个整数造成一个元素的引用在数组之外或者数组对象的最后一个元素之后,这种行为是 undefined ,但是经常造成缓冲器溢出或者缓冲器欠载运行,这经常被exploited 运行任意代码。迭代器和标准模板库容器展现出与指针和数组一样的行为和警告。

If adding or subtracting an integer to a pointer results in a reference to an element outside the array or one past the last element of the array object, the behavior is undefined but frequently leads to a buffer overflow or buffer underrun, which can often be exploited to run arbitrary code. Iterators and standard template library containers exhibit the same behavior and caveats as pointers and arrays.

Rule Severity Likelihood Remediation Cost Priority Level
CTR55-CPP High Likely Medium P18 L1

Automated Detection

Tool Version Checker Description
LDRA tool suite img 567 S** ** Enhanced Enforcement
Parasoft C/C++test img CERT_CPP-CTR55-a Do not add or subtract a constant with a value greater than one from an iterator

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

SEI CERT C Coding Standard ARR30-C. Do not form or use out-of-bounds pointers or array subscripts
MITRE CWE CWE 129, Unchecked Array Indexing

Bibliography

[Banahan 2003] Section 5.3, “Pointers” Section 5.7, “Expressions Involving Pointers”
[ISO/IEC 14882-2014] Subclause 5.7, “Additive Operators” Subclause 24.2.1, “In General”
[VU#162289]

SEI CERT C++ Coding Standard > SEI CERT C++ Coding Standard > button_arrow_left.png SEI CERT C++ Coding Standard > SEI CERT C++ Coding Standard > button_arrow_up.png SEI CERT C++ Coding Standard > SEI CERT C++ Coding Standard > button_arrow_right.png