Versions Compared

Key

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

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 to std::terminate() is implementation-defined.

The default terminate handler called by std::terminate() calls std::abort(), which abnormally terminates the process. When std::abort() is called, or if the implementation does not unwind the stack prior to calling std::terminate(), destructors for objects may not be called and external resources can be left in an indeterminate state. Abnormal process termination is the typical vector for denial-of-service attacks. For more information on implicitly calling std::terminate(), see ERR50-CPP. Do not call std::terminate(), std::abort(), or std::_Exit()abruptly terminate the program.

All exceptions thrown by an application must be caught by a matching exception handler. Even if the exception cannot be gracefully recovered from, this using the matching exception handler ensures that the stack will be properly unwound , and provide provides an opportunity to gracefully manage external resources prior to before terminating the process.

As per ERR50-CPP-EX1, a program that encounters an 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 noncompliant code example, the function neither f() does not catch  nor main() catch exceptions thrown by throwing_func(). Since Because no matching handler can be found for the exception thrown, std::terminate() is called.

...

In this compliant solution, the main entrypoint handles entry point handles all exceptions. This , which ensures that the stack is unwound up to the main() function , and allows for graceful management of external resources:.

Code Block
bgColor#ccccff
langcpp
void throwing_func() noexcept(false);
 
void f() {
  throwing_func();
}
 
int main() {
  try {
    f();
  } catch (...) {
    // Handle error
  }
}

...

In this noncompliant code example, the thread entrypoint entry point function thread_start() does not catch exceptions thrown by throwing_func(). If the initial thread function exits due to because an exception being is thrown, std::terminate() is called.

...

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();
}

...

Allowing the application to abnormally terminate can lead to resources not being freed, closed, etcand so on. It is frequently a vector for denial-of-service attacks.

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

ERR31

ERR51-CPP

Low

Probable

Medium

P4

L3

Automated Detection

Tool

Version

Checker

Description

 

 

 

Astrée

Include Page
Astrée_V
Astrée_V

main-function-catch-all
early-catch-all
Partially checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC++-ERR51
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.STRUCT.UCTCH

Unreachable Catch

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C++4035, C++4036, C++4037


Klocwork
Include Page
Klocwork_V
Klocwork_V

MISRA.CATCH.ALL


LDRA tool suite
Include Page
LDRA_V
LDRA_V

527 S

Partially implemented

Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_CPP-ERR51-a
CERT_CPP-ERR51-b

Always catch exceptions
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

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C++: ERR51-CPPChecks for unhandled exceptions (rule partially covered)
RuleChecker
Include Page
RuleChecker_V
RuleChecker_V
main-function-catch-all
early-catch-all

Partially checked
 

Related Vulnerabilities

Search for other vulnerabilities  resulting 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.

MITRE CWECWE-754, Improper Check for Unusual or Exceptional Conditions

Bibliography

[ISO/IEC 14882-2014]

Subclause 15.1, "Throwing an Exception"
Subclause 15.3, "Handling an Exception"
Subclause 15.5.1, "The std::terminate() Function"

[MISRA
08
2008]Rule 15-3-2
, "There should be at least one exception handler to catch all otherwise unhandled exceptions"
(Advisory)
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"
(Required)


...

Image Modified Image Modified Image Modified