CERT C: Rule MSC39-C

Не вызывайте va_arg () на va_list, который имеет неопределенное значение

Описание

Управляйте определением

Не вызывайте va_arg () на va_list, который имеет неопределенный value.[1]

Реализация Polyspace

Это средство проверки проверяет на Использование неопределенных va_list значений.

Примеры

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

Проблема

Эта проблема происходит когда:

  • Вы используете локальный va_list не инициализируя его сначала использование va_start или va_copy.

    Вы можете использовать локальный va_list в va_arg или vprintf- как функция (функция, которая берет переменное количество аргументов).

  • Вы используете va_list (список аргументов переменной) от параметра функции непосредственно вместо того, чтобы делать копию с помощью va_copy и использование копии.

Риск

Если вы используете локальный va_list не инициализируя его сначала, поведение не определено.

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

Фиксация

Инициализируйте локальный va_list с va_start или va_copy перед использованием его.

Передайте va_list ссылкой. В вызванной функции сделайте копию переданного va_list и используйте копию. Можно затем продолжить получать доступ к исходному va_list в функции вызова.

Пример – прямое использование va_list От другой функции
#include <stdarg.h>
#include <stdio.h>

int contains_zero(size_t count, va_list ap) {
	for (size_t i = 1; i < count; ++i) {
		if (va_arg(ap, double) == 0.0) {//Noncompliant
			return 1;
		}
	}
	return 0;
}

int print_reciprocals(size_t count, ...) {
	va_list ap; 
	va_start(ap, count);

	if (contains_zero(count, ap)) {
		va_end(ap);
		return 1;
	}

	for (size_t i = 0; i < count; ++i) {
		printf("%f ", 1.0 / va_arg(ap, double));
	}

	va_end(ap);
	return 0;
}

В этом примере, функциональном print_reciprocals распечатывает его аргументы переменной и использует функцию помощника contains_zero проверять если va_list названный ap содержит нуль. После ap передается contains_zero значением, значением ap неопределенно. Попытки считать это неопределенное значение в print_reciprocals результаты в неожиданном поведении. Polyspace® отмечает прямой из ap в th функции помощника.

Коррекция – копирует va_list Полученный из другой функции

Чтобы избежать нарушения, передайте va_list ссылкой и делают копию переменной в contains_zero функция. Выполните дальнейшие операции на копии.

#include <stdarg.h>
#include <stdio.h>

int contains_zero(size_t count, va_list *ap) {
	va_list ap1;
	va_copy(ap1, *ap);
	for (size_t i = 1; i < count; ++i) {
		if (va_arg(ap1, double) == 0.0) {
			return 1;
		}
	}
	va_end(ap1);
	return 0;
}

int print_reciprocals(size_t count, ...) {
	int status;
	va_list ap;
	va_start(ap, count);

	if (contains_zero(count, &ap)) {
		printf("0 in arguments!\n");
		status = 1;
	} else {
		for (size_t i = 0; i < count; i++) {
			printf("%f ", 1.0 / va_arg(ap, double));
		}
		printf("\n");
		status = 0;
	}

	va_end(ap);
	return status;
}

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

Группа: правило 48. Разное (MSC)
Введенный в R2019a

[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

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

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