When an exception is thrown, control is transferred to the nearest handler with a type that matches the type of the exception thrown. If no matching handler is directly found within the handlers for a try block in which the exception is thrown, the search for a matching handler continues to dynamically search for handlers in the surrounding try blocks of the same thread. The C++ Standard, [except.handle], paragraph 9 [ISO/IEC 14882-2014], states the following:
If no matching handler is found, the function
std::terminate()
is called; whether or not the stack is unwound before this call tostd::terminate()
is implementation-defined.
...
As per ERR50-CPP-EX1, a program that encounters an un-recoverable unrecoverable exception may explicitly catch the exception and terminate, but it may not allow the exception to remain uncaught. One possible solution to comply with this rule, as well as with ERR50-CPP, is for the main()
function to catch all exceptions. While this does not generally allow the application to recover from the exception gracefully, it does allow the application to terminate in a controlled fashion.
Noncompliant Code Example
...
In this compliant solution, the main entry point handles all exceptions, which ensures that the stack is unwound up to the main()
function and allows for graceful management of external resources:.
Code Block | ||||
---|---|---|---|---|
| ||||
void throwing_func() noexcept(false); void f() { throwing_func(); } int main() { try { f(); } catch (...) { // Handle error } } |
...
In this compliant solution, the thread_start()
handles all exceptions and does not rethrow, allowing the thread to terminate normally:.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <thread> void throwing_func() noexcept(false); void thread_start(void) { try { throwing_func(); } catch (...) { // Handle error } } void f() { std::thread t(thread_start); t.join(); } |
...
Allowing the application to abnormally terminate can lead to resources not being freed, closed, and so on. It is frequently a vector for denial-of-service attacks.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ERR51-CPP | Low | Probable | Medium | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| main-function-catch-all early-catch-all | Partially checked | ||||||
Axivion Bauhaus Suite |
| CertC++-ERR51 | |||||||
CodeSonar |
| LANG.STRUCT.UCTCH | Unreachable Catch | ||||||
Helix QAC |
| C++4035, C++4036, C++4037 | |||||||
Klocwork |
| MISRA.CATCH.ALL | |||||||
LDRA tool suite |
| 527 S | Partially implemented | ||||||
Parasoft C/C++test |
EXCEPT-13
| CERT_CPP-ERR51-a | Always catch exceptions | |||||||
Polyspace Bug Finder |
| CERT C++: ERR51-CPP | Checks for unhandled exceptions (rule partially covered) | ||||||
RuleChecker |
| main-function-catch-all early-catch-all | Partially checked |
Related Vulnerabilities
Search for other vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
...
This rule is a subset of ERR50-CPP. Do not abruptly terminate the program.
Bibliography
[ISO/IEC 14882-2014] | Subclause 15.1, "Throwing an Exception" |
[MISRA |
2008] | Rule 15-3-2 (Advisory) Rule 15-3-4 (Required) |
...
...