原文链接:

CTR53-CPP. Use valid iterator ranges

https://wiki.sei.cmu.edu/confluence/display/cplusplus/CTR53-CPP.+Use+valid+iterator+ranges

当遍历一个容器的元素时,迭代器必须在有效范围内迭代。一个迭代器的范围是一对迭代器,分别指向首个元素和尾后元素。

一个有效迭代器范围有以下全部特点:

一个空的迭代器范围 (两个迭代器均有效并且相等) 也是被认为是有效的。

使用两个无效的迭代器的范围或者没有指向同一个容器导致 未定义行为.

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

在这个不合规的代码示例中,两个迭代器将范围限定在同一个迭代器中,但是第一个迭代器不是先于第二个迭代器。在它的内部循环迭代中,std::for_each() 比较第一个迭代器 (在累加之后) 和第二个迭代器是否相等;只要它们不等,它就继续递增第一个迭代器。递增表示范围内尾后元素的迭代器导致 undefined behavior.

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.

1
2
3
4
5
6
7
#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; });
}

无效迭代器范围也可能是由于对两个相等的值返回 true 的比较函数造成。查看 CTR57-CPP. Provide a valid ordering predicate 获取更多关于比较器的信息。

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

在这个合规方案中,这个传入std::for_each() 迭代器的值是恰当的顺序。

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

1
2
3
4
5
6
7
#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

在这个不合规的代码示例中,来自不同容器的迭代器被传递了同一个迭代器范围。即使很多 STL implementations 将编译这块代码,程序可能表现得和开发者期望的一样,一个 STL 的实现将默认初始化的迭代器视为 end() 返回的迭代器的同义词不是必要的。

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().

1
2
3
4
5
6
7
8
#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

在这个合规方案中,通过调用 end() 生成的正确的迭代器被传入。

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

1
2
3
4
5
6
7
#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

Automated Detection

Tool Version Checker Description
Parasoft C/C++test img CERT_CPP-CTR53-a CERT_CPP-CTR53-b Do not use an iterator range that isn’t really a range Do not compare iterators from different containers
PRQA QA-C++ img 3802
PVS-Studio img V539, V662, V789

In Fun with erase(), Chris Rohlf discusses the exploit potential of a program that calls vector::erase() with invalid iterator ranges [Rohlf 2009].

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

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”

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