Main Content

CERT C++: ERR55-CPP

Honor exception specifications

Since R2020b

Description

Rule Definition

Honor exception specifications1

Polyspace Implementation

The rule checker checks for Noexcept functions exiting with exception.

Examples

expand all

Issue

This defect occurs when a noexcept entity might exit with an exception. The compiler omits the exception handing process for noexcept entities. When such an entity exits with an exception, the exception becomes unhandled, leading to abnormal program termination.

When a noexcept entity invokes other callable entities, Polyspace® makes certain assumptions to calculate whether there might be unhandled exceptions.

  • Function: When a noexcept function calls another function, Polyspace checks whether the called function might raise an exception only if it is specified as noexcept(<false>). If the called function is specified as noexcept, Polyspace assumes that it does not raise an exception. Some standard library functions, such as the constructor of std::string, use pointers to functions to perform memory allocation, which might raise exceptions. Because these functions are not specified as noexcept(<false>), Polyspace does not flag a function that calls these standard library functions.

  • External function: When a noexcept function calls an external function, Polyspace flags the function declaration if the external function is specified as noexcept(<false>).

  • Virtual function: When a function calls a virtual function, Polyspace flags the function declaration if the virtual function is specified as noexcept(<false>) in a derived class. For instance, if a noexcept function calls a virtual function that is declared as noexcept(<true>) in the base class, and noexcept(<false>) in a subsequent derived class, Polyspace flags the declaration of the noexcept function.

  • Pointers to function: When a noexcept function invokes a pointer to a function, Polyspace assumes that the pointer to the function does not raise exceptions.

When analyzing whether a function raises unhandled exceptions, Polyspace ignores:

  • Exceptions raised in destructors

  • Exceptions raised in atexit() operations

Polyspace also ignores the dynamic context when checking for exceptions. For instance, a function might raise unhandled exceptions only in certain dynamic contexts. Polyspace flags such a function even if the exception might not be raised.

Risk

If a noexcept function exits with an exception, the compiler invokes std::terminate() implicitly. The function std::terminate() terminates the program execution in an implementation-defined manner. That is, the exact process of program termination depends on the particular set of software and hardware that you use. For instance, std:terminate() might invoke std::abort() to abnormally abort the execution without unwinding the stack, leading to resource leak and security vulnerabilities.

Fix

Specify a function as noexcept or noexcept(true) only when you know that the function does not exit with an exception. If you are not sure, specify it by using noexcept(false)

Example

Consider this code where two functions are specified as noexcept. Polyspace statically analyzes these functions and the functions that they call.

#include <stdexcept>
#include <typeinfo>
bool f(bool flag){
	if(flag==true)
	throw flag;
	return flag;
	
}
void LibraryFunc_noexcept_false() noexcept(false);  
void SpecFalseCT() noexcept  // Noncompliant
{
	try {
		LibraryFunc_noexcept_false();
	} catch (int &e) {
		LibraryFunc_noexcept_false();  
	} catch (std::exception &e) {
	} catch (...) {
	}
}
bool flag = false;
void Caller() noexcept {          //Noncompliant
	try {
		if(f(flag)){
			//...
		}
	} catch (int i) {
		//...
	} 
}

  • Polyspace flags the noexcept function SpecFaleCT() because this function calls the noexcept(false) external function LibraryFunc_noexcept_false() without handling any exceptions that can be raised from it. These exceptions can cause the noexcept function to exit with an exception.

  • Polyspace flags the noexcept function Caller because this function calls the noexcept(false) function f(), which contains an explicit throw statement. Even though the throw statement is not executed when flag is false, Polyspace ignores the dynamic context and flags Caller.

Correction

When defining functions, specify them as noexcept only when all possible exceptions are handled within the function. Otherwise, specify them as noexcept(false). In cases where an exception is not raised in the dynamic context, justify this defect by using comments.

#include <stdexcept>
#include <typeinfo>
bool f(bool flag){
	if(flag==true)
	throw flag;
	return flag;
	
}
void LibraryFunc_noexcept_false() noexcept(false);  
void SpecFalseCT() noexcept(false)// Compliant
{
	try {
		LibraryFunc_noexcept_false();
	} catch (int &e) {
		LibraryFunc_noexcept_false();  
	} catch (std::exception &e) {
	} catch (...) {
	}
}
bool flag = false;
void Caller() noexcept{//Noncompliant // polyspace CERT-CPP:ERR55-CPP 
//[Justified:Unset] "Exception is not thrown when flag is false"
	try {
		if(f(flag)){
			//...
		}
	} catch (int i) {
		//...
	} 
}

  • The function SpecFalseCT is now specified as noexcept(false) because it calls an external function that can raise exceptions. This function is compliant with this rule.

  • The function f() does not raise an exception when flag is false. The function Caller honors its exception specification, but Polyspace flags it because Polyspace ignores dynamic context. This defect is justified by using a comment.

Check Information

Group: 08. Exceptions and Error Handling (ERR)

Version History

Introduced in R2020b


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.