CertC++-ERR55

Honor exception specifications

Required inputs: IR, StaticSemanticAnalysis

The C++ Standard, [except.spec], paragraph 8 [ ISO/IEC 14882-2014], states the following:

A function is said to allow an exception of type E if the constant-expression in its noexcept-specification evaluates to false or its dynamic-exception-specification contains a type T for which a handler of type T would be a match (15.3) for an exception of type E.

If a function declared with a dynamic-exception-specification throws an exception of a type that would not match the exception-specification, the function std::unexpected() is called. The behavior of this function can be overridden but, by default, causes an exception of std::bad_exception to be thrown. Unless std::bad_exception is listed in the exception-specification, the function  std::terminate() will be called.

Similarly, if a function declared with a noexcept-specification throws an exception of a type that would cause the noexcept-specification to evaluate to  false, the function  std::terminate() will be called.

Calling  std::terminate() leads to implementation-defined termination of the program. To prevent abnormal termination of the program, any function that declares an exception-specification should restrict itself, as well as any functions it calls, to throwing only allowed exceptions.

Noncompliant Code Example

In this noncompliant code example, a function is declared as nonthrowing, but it is possible for  std::vector::resize() to throw an exception when the requested memory cannot be allocated.

#include <cstddef>
#include <vector>
 
void f(std::vector<int> &v, size_t s) noexcept(true) {
  v.resize(s); // May throw
}
Compliant Solution

In this compliant solution, the function's noexcept-specification is removed, signifying that the function allows all exceptions.

#include <cstddef>
#include <vector>

void f(std::vector<int> &v, size_t s) {
  v.resize(s); // May throw, but that is okay
}
Noncompliant Code Example

In this noncompliant code example, the second function claims to throw only Exception1, but it may also throw Exception2.

#include <exception>
 
class Exception1 : public std::exception {};
class Exception2 : public std::exception {};

void foo() {
  throw Exception2{}; // Okay because foo() promises nothing about exceptions
}

void bar() throw (Exception1) {
  foo();    // Bad because foo() can throw Exception2
}
Compliant Solution

This compliant solution catches the exceptions thrown by  foo().

#include <exception>

class Exception1 : public std::exception {};
class Exception2 : public std::exception {};

void foo() {
  throw Exception2{}; // Okay because foo() promises nothing about exceptions
}

void bar() throw (Exception1) {
  try {
    foo();
  } catch (Exception2 e) {
    // Handle error without rethrowing it
  }
}
Compliant Solution

This compliant solution declares a dynamic exception-specification for  bar(), which covers all of the exceptions that can be thrown from it.

#include <exception>

class Exception1 : public std::exception {};
class Exception2 : public std::exception {};

void foo() {
  throw Exception2{}; // Okay because foo() promises nothing about exceptions
}

void bar() throw (Exception1, Exception2) {
  foo();
}
Implementation Details

Some vendors provide language extensions for specifying whether or not a function throws. For instance, Microsoft Visual Studio provides  __declspec(nothrow)), and Clangsupports  __attribute__((nothrow)). Currently, the vendors do not document the behavior of specifying a nonthrowing function using these extensions. Throwing from a function declared with one of these language extensions is presumed to be undefined behavior.

Risk Assessment

Throwing unexpected exceptions disrupts control flow and can cause premature termination and denial of service.

Rule Severity Likelihood Remediation Cost Priority Level
ERR55-CPP Low Likely Low P9 L2
Related Guidelines
SEI CERT C++ Coding Standard ERR50-CPP. Do not abruptly terminate the program
Bibliography
[ GNU 2016] "Declaring Attributes of Functions"
[ ISO/IEC 14882-2014] Subclause 15.4, "Exception Specifications"
[ MSDN 2016] " nothrow (C++)"
Excerpt from SEI CERT C++ Coding Standard [https://cmu-sei.github.io/secure-coding-standards/sei-cert-cpp-coding-standard/rules/exceptions-and-error-handling-err/err55-cpp], Copyright (C) 1995-2026 Carnegie Mellon University. See section 9.4. "3rd-Party Licenses" in the documentation for full details.

Possible Messages

Key

Text

Severity

Disabled

exception_specification_violation

Exception violates function’s exception-specification.

None

False

exception_specification_violation_from_call

Exceptions propagated from this call violate function’s exception-specification.

None

False

Options

exclude_exception_base_classes

exclude_exception_base_classes : set[bauhaus.analysis.config.QualifiedName] = set()

Exclude issues for the exception types mentioned in this set of qualified names. Also excludes classes derived from those class names as well as pointers or references to any of these class types.
 

generate_violation_path

generate_violation_path : bool = True

Whether to compute a trace for the exception. This improves the usability of the violation description, but requires additional computing which might slow down the rule.
 

ignore_constructor_destructor

ignore_constructor_destructor : bool = False

Whether to ignore escaping exceptions from constructors and destructors.
 

ignore_unknown_routines

ignore_unknown_routines : bool = False

Whether to ignore extern or only declared routines.