The std::abort()
and std::_Exit()
functions are used to terminate the program in an immediate fashion. They do so without calling exit handlers registered with std::atexit()
, and without executing destructors for objects with automatic, thread, or static storage duration. It is implementation-defined as to whether open streams with unwritten buffered data are flushed, open streams are closed, or temporary files are removed [ISO/IEC 9899:1999]. Because these functions can leave external resources in an indeterminate state, they should only be called explicitly in direct response to a critical error in the application.
...
In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before
std::terminate()
is called. In the situation where the search for a handler encounters the outermost block of a function with a noexcept-specification that does not allow the exception, it is implementation-defined whether the stack is unwound, unwound partially, or not unwound at all beforestd::terminate()
is called. In all other situations, the stack shall not be unwound beforestd::terminate()
is called.
Do not allow an implicit call to explicitly or implicitly call std::abort()
or std::_Exit()
. When the default terminate_handler
is installed, or the current terminate_handler
responds by calling std::abort()
or std::_Exit()
, do not allow an implicit call to explicitly or implicitly call std::terminate()
. Abnormal process termination is the typical vector for denial of service attacks.It is acceptable to call std::abort()
, std::_Exit()
, or std::terminate()
in response to a critical program error for which no recovery is possible, after indicating the nature of the problem to the operator.
Noncompliant Code Example
In this noncompliant code example, the thread entrypoint function thread_start()
does not catch exceptions thrown by throwing_func()
. If the initial thread function exits due to an exception being thrown, std::terminate()
is called.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <thread> void throwing_func() noexcept(false); void thread_start(void) { throwing_func(); } void f() { std::thread t(thread_start); t.join(); } |
Compliant Solution
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(); } |
Noncompliant Code Example
In this noncompliant code example, the call to f()
, which was registered as an exit handler with std::at_exit()
, may result in a call to std::terminate()
because throwing_func()
may throw an exception:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <cstdlib> void throwing_func() noexcept(false); void f() { throwing_func(); } int main() { if (0 != std::at_exit(f)) { // Handle error } // ... } |
Compliant Solution
In this compliant solution, f()
handles all exceptions thrown by throwing_func()
, and does not rethrow:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <cstdlib> void throwing_func() noexcept(false); void f() { try { throwing_func(); } catch (...) { // Handle error } } int main() { if (0 != std::at_exit(f)) { // Handle error } // ... } |
Exceptions
ERR30-CPP-EX1: It is acceptable to explicitly call std::abort()
, std::_Exit()
, or std::terminate()
in response to a critical program error for which no recovery is possible, after indicating the nature of the problem to the operator, as in this example:
Code Block | ||||
---|---|---|---|---|
| ||||
#include <exception>
void report(const char *msg) noexcept;
[[noreturn]] void fast_fail(const char *msg) {
// Report error message to operator.
report(msg);
// Terminate
std::terminate();
}
void critical_function_that_fails() noexcept(false);
void f() {
try {
critical_function_that_fails();
} catch (...) {
fast_fail("Critical function failure");
}
} |
Risk Assessment
Allowing the application to abnormally terminate in an implicit manner can lead to resources not being freed, closed, etc. It is frequently a vector for denial-of-service attacks.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
ERR30-CPP | Low | Probable | Medium | P4 | L3 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
| 4037, 4038, 4636, 4637 |
Related Vulnerabilities
Search for other vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Bibliography
[ISO/IEC 14882-2014] | 15.5.1, "The |
[ISO/IEC 9899:1999] | 7.20.4.1, "The abort Function"7.20.4.4, "The _Exit Function" |
[MISRA 08] | Rule 15-3-2, "There should be at least one exception handler to catch all otherwise unhandled exceptions" Rule 15-3-4, "Each exception explicitly thrown in the code shall have a handler of a compatible type in all call paths that could lead to that point" |
...