CERT C: Rule MSC39-C

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

Описание

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

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

Реализация Polyspace

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

Примеры

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

Проблема

Эта проблема возникает, когда:

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

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

  • Вы используете 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 в функции helper.

Коррекция - Копирование 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 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

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

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