It is important that resources are reclaimed when exceptions are thrown. Throwing an exception may result in cleanup code being bypassed. As a result, it is the responsibility of the exception handler to properly clean up. This may be problematic if the exception is to be caught in a different function or module. Instead, it is preferable if resources are reclaimed automatically when objects go out of scope.
In this non-compliant code example, the resources associated with the object pointed to by pst are not recovered in the event that processItem throws an exception, thereby potentially causing a resource leak.
while (moreToDo) {
SomeType *pst = new SomeType();
try {
pst->processItem();
}
catch (...) {
// deal with exception
throw;
}
delete pst;
}
|
In this code, the exception handler recovers the resources associated with the object pointed to by pst.
while (moreToDo) {
SomeType *pst = new SomeType();
try {
pst->processItem();
}
catch (...) {
// deal with exception
delete pst;
throw;
}
delete pst;
} |
Handling resource cleanup in catch clauses does work, but can have several disadvantages:
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. A judicious unique_ptr would free the resource whether an error occurs or not.
while (moreToDo) {
std::unique_ptr<SomeType> pst = new SomeType();
try {
pst->processItem();
}
catch (...) {
// deal with exception
throw; // pst automatically freed
}
// pst automatically freed
}
|
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 |
|---|---|---|---|---|---|
MEM44-CPP | low | probable | high | P2 | L3 |
[Meyers 96] Item 9: "Use destructors to prevent resource leaks".