...
Resources must not be leaked as a result of throwing an exception, including during the construction of an object.
Noncompliant Code Example
In this noncompliant code example, pst
is not properly released when processItem
throws an exception, causing a resource leak:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <new> struct SomeType { void processItem() noexcept(false); }; void f() { SomeType *pst = new (std::nothrow) SomeType(); if (!pst) { // Handle error return; } try { pst->processItem(); } catch (...) { // Handle error throw; } delete pst; } |
Compliant Solution (delete
)
In this compliant solution, the exception handler frees pst
by calling delete
:
...
- Each distinct cleanup requires its own try & catch blocks.
- The cleanup operation must not throw any exceptions.
Compliant Solution (RAII Design Pattern)
A better approach would be to employ RAII. This forces every object to 'clean up after itself' in the face of abnormal behavior, preventing the programmer from having to do so. This approach additionally benefits by not requiring statements to handle resource allocation errors in conformance with MEM52-CPP. Detect and handle memory allocation errors.
Code Block | ||||
---|---|---|---|---|
| ||||
struct SomeType { void processItem() noexcept(false); }; void f() { SomeType st; try { st.processItem(); } catch (...) { // Handle error throw; } } |
Noncompliant Code Example
In this noncompliant code example, the C::C()
constructor might fail to allocate memory for a
, might fail to allocate memory for b
, or might throw an exception in the init()
method. If init()
throws an exception, then neither a
nor b
will be released. Likewise, if the allocation for b
fails, then a
will not be released.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <new> struct A {/* ... */}; struct B {/* ... */}; class C { A *a; B *b; protected: void init() noexcept(false); public: C() : a(new A()), b(new B()) { init(); } }; |
Compliant Solution (try/catch
)
This compliant solution mitigates the potential failures by releasing a
and b
if an exception is thrown during their allocation or during init()
:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <new> struct A {/* ... */}; struct B {/* ... */}; class C { A *a; B *b; protected: void init() noexcept(false); public: C() : a(nullptr), b(nullptr) { try { a = new A(); b = new B(); init(); } catch (...) { delete a; delete b; throw; } } }; |
Compliant Solution (std::unique_ptr)
This compliant solution utilizies std::unique_ptr
to create objects that clean up after themselves should anything go wrong in the C::C()
constructor. See VOID MEM00-CPP. Don't use auto_ptr where copy semantics might be expected for more information on std::unique_ptr
.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <memory> struct A {/* ... */}; struct B {/* ... */}; class C { std::unique_ptr<A> a; std::unique_ptr<B> b; protected: void init() noexcept(false); public: C() : a(new A()), b(new B()) { init(); } }; |
Risk Assessment
Memory and other resource leaks will eventually cause a program to crash. If an attacker can provoke repeated resource leaks by forcing an exception to be thrown through the submission of suitably crafted data, then the attacker can mount a denial-of-service attack.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ERR40-CPP | Low | Probable | High | P2 | L3 |
Automated Detection
Tool | Version | Checker | Description |
---|---|---|---|
|
|
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
CERT C++ Coding Standard | MEM52-CPP. Detect and handle memory allocation errors MEM51-CPP. Properly deallocate dynamically allocated resources |
Bibliography
[ISO/IEC 14882-2014] | 15.2, "Constructors and Destructors" |
[Meyers 96] | Item 9: "Use destructors to prevent resource leaks". |
[Stroustrup 2001] | "Exception-Safe Implementation Techniques" |
[Cline 2009] | 17.2, "I'm still not convinced: a 4-line code snippet shows that return-codes aren't any worse than exceptions; |
...