...
Similarly, before the lifetime of an object has started but after the storage which the object will occupy has been allocated or, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, any glvalue that refers to the original object may be used but only in limited ways. For an object under construction or destruction, see 12.7. Otherwise, such a glvalue refers to allocated storage, and using the properties of the glvalue that do not depend on its value is well-defined. The program has undefined behavior if:
— an lvalue-to-rvalue conversion is applied to such a glvalue,
— the glvalue is used to access a non-static data member or call a non-static member function of the object, or
— the glvalue is bound to a reference to a virtual base class, or
— the glvalue is used as the operand of adynamic_cast
or as the operand oftypeid
.
Do not use an object outside of its lifetime, except in the ways described above as being well-defined.
...
Code Block | ||||
---|---|---|---|---|
| ||||
auto g() { int i = 12; return [=] () mutable { i = 100; return i; }; } void f() { int i = g()(); } |
Noncompliant Code Example
A std::initializer_list<>
object is constructed from an initializer list as if the implementation allocated a temporary array and passed it to the std::initializer_list<>
constructor. This temporary array has the same lifetime as other temporary objects, except that initializing a std::initializer_list<>
object from the array extends the lifetime of the array exactly like binding a reference to a temporary [ISO/IEC 14882-2014]. In this noncompliant code example, a member variable of type std::initializer_list<int>
is list initialized within the constructor's ctor-initializier. Under these circumstances, the conceptual temporary array's lifetime ends once the constructor exits, and so accessing any elements of the std::initializer_list<int>
member variable results in undefined behavior.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <initializer_list>
#include <iostream>
class C {
std::initializer_list<int> L;
public:
C() : L{1, 2, 3} {}
int first() const { return *L.begin(); }
};
void f() {
C c;
std::cout << c.first();
} |
Compliant Solution
In this compliant solution, the std::initializer_list<int>
member variable is replaced with a std::vector<int>
, which copies the elements of the initializer list to the container instead of relying on a dangling reference to the temporary array.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <initializer_list>
#include <iostream>
#include <vector>
class C {
std::vector<int> L;
public:
C() : L{1, 2, 3} {}
int first() const { return *L.begin(); }
};
void f() {
C c;
std::cout << c.first();
} |
Risk Risk Assessment
Referencing an object outside of its lifetime can result in an attacker being able to run arbitrary code.
...
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Clang |
| -Wdangling-initializer-list | Catches some lifetime issues related to incorrect use of std::initializer_list<> |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
...
[ISO/IEC 14882-2014] | 3.8, "Object Lifetime" 8.5.4, "List-Initialization" |
[Coverity 2007] |
...