exponenta event banner

CERT C: 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 в функции помощника.

Исправление - Копировать 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 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

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