Throw argument raises unexpected exception

Выражение аргумента в throw оператор повышает непредвиденные исключительные ситуации, ведя к утечкам ресурсов и уязвимостям системы обеспечения безопасности

Описание

Этот дефект происходит, когда выражение аргумента оператора броска может повысить исключение. Выражения, которые могут повысить исключения, включают:

  • Функции, которые заданы как noexcept(false)

  • Функции, которые содержат один или несколько явный throw операторы

  • Конструкторы, которые выполняют операции выделения памяти

  • Выражения, которые включают динамический кастинг

Риск

При повышении исключения явным образом при помощи throw операторы, компилятор сначала создает ожидаемое исключение путем оценки аргумента оператора броска, и затем повышает ожидаемое исключение. Если непредвиденная исключительная ситуация повышена, когда компилятор создает ожидаемое исключение в throw оператор, непредвиденная исключительная ситуация распространена вместо ожидаемой. Эта непредвиденная исключительная ситуация может стать необработанным исключением. В зависимости от вашей среды компилятор может вызвать std::abort неправильно отключать выполнение программы, не раскручивая стек, когда исключения становятся необработанными, ведя к утечке ресурсов и уязвимостям системы обеспечения безопасности. Рассмотрите этот код где throw оператор повышает явное исключение класса myException.

class myException{
	myException(){
		msg = new char[10];
		//...
	}
	//...
};

foo(){
	try{
		//..
		throw myException();
	}
	catch(myException& e){
		//...
	}
}
Во время конструкции временного myException объект, new оператор может повысить bad_alloc исключение. В таком случае, throw оператор повышает bad_alloc исключение, вместо myException. Поскольку myException было ожидаемое исключение, блок выгоды несовместим с bad_alloc. bad_alloc исключение становится необработанным исключением. Это может заставить программу прерываться неправильно, не раскручивая стек, ведя к утечке ресурсов и уязвимостям системы обеспечения безопасности.

Фиксация

Избегайте использования выражений, которые могут повысить исключения в качестве аргумента в throw оператор.

Примеры

развернуть все

int f_throw() noexcept(false);
int foo(){
	try{
		//...
		throw f_throw();
	}
	catch(...){
		//...
	}
}

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

Коррекция – функции использования, заданные как noexcept(true) как выражение аргумента throw Операторы

Одна возможная коррекция должна использовать функции, которые не повышают исключения в выражении аргумента throw оператор. Эти функции заданы как noexcept(true).

int f_throw() noexcept(true);
int foo(){
	try{
		//...
		throw f_throw();
	}
	catch(...){
		//...
	}
}
class WithDynamicAlloc {
public:
	WithDynamicAlloc(int n) {
		m_data = new int[n];   
	}
	~WithDynamicAlloc() {
		delete[] m_data;
	}
private:
	int* m_data;
};
int foo(){
	try{
		//...
		throw WithDynamicAlloc(10); 
	}
	catch(WithDynamicAlloc& e){
		//... 
	}
}

В этом примере, конструкторе объекта WithDynamicAlloc выполняет операцию динамического выделения памяти. Этот конструктор может повысить исключение, такое как bad_alloc та причина силы программа, чтобы завершить работу, не раскручивая стек, приводя к утечке ресурсов и уязвимостям системы обеспечения безопасности.

Коррекция – Конструкторы Использования, который Не Выделяет Память как Выражение Аргумента throw Операторы

Одна возможная коррекция должна использовать объекты, которые не требуют динамического выделения памяти как объектов исключения.

class WithoutDynamicAlloc {
public:
	WithoutDynamicAlloc(int n) : m_data(n){   
	}
	~WithoutDynamicAlloc() {
	}
private:
	int m_data;
};
int foo(){
	try{
		//...
		throw WithoutDynamicAlloc(10); 
	}
	catch(WithoutDynamicAlloc& e){
		//... 
	}
}
int MightThrow(bool b) {
	if (b) {
		throw 2.1;
	}
	return 42;
}
int foo(){
	try{
		//...
		throw MightThrow(false);
		throw MightThrow(true);
	}
	catch(int e){
		//... 
	}
}

В этом примере, функциональном MightThrow() повышает исключение в зависимости от входа b. Поскольку Polyspace® анализирует функции статически, он принимает тот MightThrow() исключения повышений независимо от входа и повышения нарушение этого средства проверки на обоих throw MightThrow(true) и throw MightThrow(false).

Коррекция – комментарии использования, чтобы выровнять по ширине результат

Поскольку MightThrow(false) не повышает исключение, возможная коррекция должна использовать комментарии, чтобы выровнять по ширине оператор throw MightThrow(false)Результаты.SeeAddress Polyspace через исправления ошибок или выравнивания

int MightThrow(bool b) {
	if (b) {
		throw 2.1;
	}
	return 42;
}
int foo(){
	try{
		//...
		throw MightThrow(false);// polyspace DEFECT:THROW_THROWS [Justified:Low] "Does not Throw"
		throw MightThrow(true);
	}
	catch(int e){
		//... 
	}
}

Информация о результате

Группа: исключение C++
Язык: C++
Значение по умолчанию: На для рукописного кода, прочь для сгенерированного кода
Синтаксис командной строки: THROW_ARGUMENT_EXPRESSION_THROWS
Удар: высоко
Введенный в R2020b