Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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 before std::terminate() is called. In all other situations, the stack shall not be unwound before std::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
bgColor#FFcccc
langcpp
#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
bgColor#ccccff
langcpp
#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
bgColor#FFcccc
langcpp
#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
bgColor#ccccff
langcpp
#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
bgColor#ccccff
langcpp
#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

PRQA QA-C++

Include Page
PRQA QA-C++_V
PRQA QA-C++_V

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 std::terminate() Function"
18.5, "Start and Termination" 

[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"

...