CERT C++: ERR55-CPP

Спецификации исключений Honor

Описание

Определение правила

Спецификации исключений Honor[1]

Реализация Polyspace

Эта проверка проверяет на наличие функций Noexcept, выходящих за исключением.

Примеры

расширить все

Проблема

Этот дефект возникает, когда noexcept сущность может выйти за исключением. Компилятор опускает процесс передачи исключений для noexcept сущности. Когда такая сущность выходит за исключением, исключение становится необработанным, что приводит к ненормальному завершению программы.

Когда noexcept сущность вызывает другие вызываемые сущности, Polyspace® делает определенные предположения, чтобы вычислить, могут ли быть необработанные исключения.

  • Функция: Когда noexcept функция вызывает другую функцию, Polyspace проверяет, может ли вызываемая функция вызвать исключение, только если оно задано как noexcept(<false>). Если вызываемая функция задана как noexceptPolyspace принимает, что это не вызывает исключение. Некоторые стандартные функции библиотеки, такие как конструктор std::string, используйте указатели на функции для выполнения выделения памяти, что может вызвать исключения. Потому что эти функции не заданы как noexcept(<false>)Polyspace не помечает функцию, которая вызывает эти стандартные функции библиотеки.

  • Внешняя функция: Когда noexcept функция вызывает внешнюю функцию, Polyspace помечает объявление функции, если внешняя функция задана как noexcept(<false>).

  • Виртуальная функция: Когда функция вызывает виртуальную функцию, Polyspace помечает объявление функции, если виртуальная функция задана как noexcept(<false>) в производном классе. Для образца, если a noexcept функция вызывает виртуальную функцию, которая объявлена как noexcept(<true>) в базовом классе и noexcept(<false>) в последующем производном классе Polyspace помечает объявление noexcept функция.

  • Указатели на функцию: Когда noexcept функция вызывает указатель на функцию, Polyspace принимает, что указатель на функцию не вызывает исключений.

При анализе, вызывает ли функция необработанные исключения, Polyspace игнорирует:

  • Исключения, вызванные деструкторами

  • Исключения, высказанные в atexit() операции

Polyspace также игнорирует динамический контекст при проверке на исключения. Например, функция может вызывать необработанные исключения только в определенных динамических контекстах. Polyspace помечает такую функцию, даже если исключение может не быть вызвано.

Риск

Если a noexcept функция выходит за исключением, компилятор вызывает std::terminate() неявно. Функция std::terminate() завершает выполнение программы определенным в реализации способом. То есть точный процесс завершения программы зависит от конкретного набора программного и оборудования, которое вы используете. Для образца, std:terminate() может вызвать std::abort() аномально прервать выполнение без размотки стека, что приводит к утечке ресурсов и уязвимостям безопасности.

Зафиксировать

Задайте функцию следующим noexcept или noexcept(true) только когда вы знаете, что функция не выходит за исключением. Если вы не уверены, задайте его при помощи noexcept(false)

Пример

Рассмотрим этот код, где две функции заданы как noexcept. Polyspace статически анализирует эти функции и функции, которые они вызывают.

#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 помечает noexcept функциональные SpecFaleCT() потому что эта функция вызывает noexcept(false) внешние функциональные LibraryFunc_noexcept_false() без обработки каких-либо исключений, которые могут быть вызваны из него. Эти исключения могут вызвать noexcept функция для выхода за исключением.

  • Polyspace помечает noexcept функциональные Caller потому что эта функция вызывает noexcept(false) функциональные f(), который содержит явное throw оператор. Хотя и throw оператор не выполняется, когда flag является falsePolyspace игнорирует динамический контекст и флаги Caller.

Коррекция

При определении функций задайте их как noexcept только при обработке всех возможных исключений в функции. В противном случае задайте их следующим noexcept(false). В тех случаях, когда исключение не возникает в динамическом контексте, разъясните этот дефект с помощью комментариев.

#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) {
		//...
	} 
}

  • Функция SpecFalseCT теперь задается как noexcept(false) потому что она вызывает внешнюю функцию, которая может вызывать исключения. Эта функция соответствует этому правилу.

  • Функция f() не вызывает исключение, когда flag является false. Функция Caller поддерживает спецификацию исключения, но Polyspace помечает ее, потому что Polyspace игнорирует динамический контекст. Этот дефект обоснован использованием комментария.

Проверяйте информацию

Группа: 08. Исключения и обработка ошибок (ERR)
Введенный в R2020b

[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОН И/ИЛИ ЕГО ИНЖЕНЕРНОГО ИНСТИТУТА ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ НА БАЗИСЕ «КАК ЕСТЬ». УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБОГО ВОПРОСА, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИЮ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ КОММЕРЧЕСКОЙ ВЫГОДЫ, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Это программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллон или его Институтом программной инженерии.