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 tofalse
or its dynamic-exception-specification contains a typeT
for which a handler of typeT
would 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- declared with an exception-specification throws an exception of a type that would not included in match the exception-specification, the function std::unexpected()
is called. The behaviour behavior of this function can be overridden within a projectbut, 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 will be called, leading 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 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 exceptions listed in its exception-specification.
...
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.
Code Block | ||||
---|---|---|---|---|
| ||||
#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.
Code Block | ||||
---|---|---|---|---|
| ||||
#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 non-compliant noncompliant code example, the second function claims to throw only exception1
Exception1
, but it may also throw exception2
Exception2.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <exception> class exception1Exception1 : public std::exception {}; class exception2Exception2 : public std::exception {}; void foo() { throw exception2Exception2{}; // ok...sinceOkay because foo() promises nothing wrtabout exceptions } void bar() throw (exception1Exception1) { foo(); // bad,Bad sincebecause foo() can throw exception2Exception2 } |
Compliant Solution
A simple This compliant solution is to catch any catches the exceptions thrown by foo{}by foo().
Code Block | |||||
---|---|---|---|---|---|
| |||||
#include <exception> class Exception1 : public std::exception {}; class Exception2 : public std::exception {}; void foo() { throw Exception2{}; // Okay because foo() promises nothing about exceptions } void void bar() throw (exception1Exception1) { try { foo(); } catch (...Exception2 e) { // handleHandle error, without re-throwing it } } 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.
Code Block | ||||
---|---|---|---|---|
| ||||
#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 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.
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 |
1 (low)
3 (likely)
1 (low)
P3
L3
References
Wiki Markup |
---|
\[[ISO/IEC 14882-2003|AA. C++ References#ISO/IEC 14882-2003]\]
\[[MISRA 08|AA. C++ References#MISRA 08]\] Rule 15-5-2 |
Low | Likely | Low | P9 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| unhandled-throw-noexcept | Partially checked | ||||||
Axivion Bauhaus Suite |
| CertC++-ERR55 | |||||||
CodeSonar |
| LANG.STRUCT.EXCP.THROW | Use of throw | ||||||
Helix QAC |
| C++4035, C++4036, C++4632 | |||||||
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) | ||||||
Polyspace Bug Finder |
| CERT C++: ERR55-CPP | Checks for noexcept functions exiting with exception (rule fully covered) | ||||||
RuleChecker |
| unhandled-throw-noexcept | Partially checked |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Bibliography
[GNU 2016] | "Declaring Attributes of Functions" |
[ISO/IEC 14882-2014] | Subclause 15.4, "Exception Specifications" |
[MSDN 2016] | "nothrow (C++)" |
...
ERR09-CPP. Throw anonymous temporaries and catch by reference 12. Exceptions and Error Handling (ERR) ERR31-CPP. Don't redefine errno