The C++ Standard, [except.spec], paragraph 8 [ISO/IEC 14882-2014], states the following:
A function is said to allow an exception of type
Eif the constant-expression in its noexcept-specification evaluates tofalseor its dynamic-exception-specification contains a typeTfor which a handler of typeTwould be a match (15.3) for an exception of typeE.
If a function throws an exception other than one allowed by its exception-specification, it can lead to an implementation-defined termination of the program ([except.spec], paragraph 9).
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.
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
}
|
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
} |
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
}
|
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
}
}
|
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();
} |
Some vendors provide language extensions for specifying whether or not a function throws. For instance, Microsoft Visual Studio provides __declspec(nothrow)), and Clang supports __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.
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 |
Tool | Version | Checker | Description |
|---|---|---|---|
| Axivion Bauhaus Suite | CertC++-ERR55 | ||
| LDRA tool suite | 56 D | Partially implemented | |
| Parasoft C/C++Test | CERT_CPP-ERR55-a | Where a function's declaration includes an exception-specification, the function shall only be capable of throwing exceptions of the indicated type(s) | |
| PRQA QA-C++ | 4035, 4036, 4632 |
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
| SEI CERT C++ Coding Standard | ERR50-CPP. Do not abruptly terminate the program |
| [GNU 2016] | "Declaring Attributes of Functions" |
| [ISO/IEC 14882-2014] | Subclause 15.4, "Exception Specifications" |
| [MSDN 2016] | "nothrow (C++)" |