Skip to content

Commit a8718f9

Browse files
committed
C++: Add qhelp for 'cpp/iterator-to-expired-container'.
1 parent 3a8db49 commit a8718f9

File tree

2 files changed

+73
-0
lines changed

2 files changed

+73
-0
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>
7+
Using an iterator owned by a container after the lifetime of the container has expired can lead to undefined behavior.
8+
This is because the iterator may be invalidated when the container is destroyed, and dereferencing an invalidated iterator is undefined behavior.
9+
These problems can be hard to spot due to C++'s complex rules for temporary object lifetimes and their extensions.
10+
</p>
11+
12+
</overview>
13+
<recommendation>
14+
15+
<p>
16+
Never create an iterator to a temporary container when the iterator is expected to be used after the container's lifetime has expired.
17+
</p>
18+
19+
</recommendation>
20+
<example>
21+
<p>
22+
23+
</p>
24+
25+
<p>
26+
The rules for lifetime extension ensures that the code in <code>lifetime_of_temp_extended</code> is well-defined. This is because the
27+
lifetime of the temporary container returned by <code>get_vector</code> is extended to the end of the loop. However, prior to C++23,
28+
the lifetime extension rules do not ensure that the container returned by <code>get_vector</code> is extended in <code>lifetime_of_temp_not_extended</code>.
29+
This is because the temporary container is not bound to a rvalue reference.
30+
</p>
31+
<sample src="IteratorToExpiredContainerExtendedLifetime.cpp" />
32+
33+
</example>
34+
<references>
35+
36+
<li>CERT C Coding Standard:
37+
<a href="https://wiki.sei.cmu.edu/confluence/display/c/MEM30-C.+Do+not+access+freed+memory">MEM30-C. Do not access freed memory</a>.</li>
38+
<li>
39+
OWASP:
40+
<a href="https://owasp.org/www-community/vulnerabilities/Using_freed_memory">Using freed memory</a>.
41+
</li>
42+
<li>
43+
<a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Lifetime.pdf">Lifetime safety: Preventing common dangling</a>
44+
</li>
45+
<li>
46+
<a href="https://en.cppreference.com/w/cpp/container">Containers library</a>
47+
</li>
48+
<li>
49+
<a href="https://en.cppreference.com/w/cpp/language/range-for">Range-based for loop (since C++11)</a>
50+
</li>
51+
52+
</references>
53+
</qhelp>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#include <vector>
2+
3+
std::vector<int> get_vector();
4+
5+
void use(int);
6+
7+
void lifetime_of_temp_extended() {
8+
for(auto x : get_vector()) {
9+
use(x); // GOOD: The lifetime of the vector returned by `get_vector()` is extended until the end of the loop.
10+
}
11+
}
12+
13+
// Writes the the values of `v` to an external log and returns it unchanged.
14+
const std::vector<int>& log_and_return_argument(const std::vector<int>& v);
15+
16+
void lifetime_of_temp_not_extended() {
17+
for(auto x : log_and_return_argument(get_vector())) {
18+
use(x); // BAD: The lifetime of the vector returned by `get_vector()` is not extended, and the behavior is undefined.
19+
}
20+
}

0 commit comments

Comments
 (0)