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_start внутри блока средство проверки рассматривает список как инициализированный за пределами блока для оставшейся части функции. Аналогично, если вы завершаете список на va_end внутри блока средство проверки рассматривает список как завершенный за пределами блока для оставшейся части функции.

Риск

При использовании локального va_list без его инициализации поведение не определено.

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

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

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

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

Пример - Прямое использование va_list Из другой функции
#include <cstdarg>
#include <cstdio>
#include <climits>
  
int containsOutliers(size_t count, va_list ap) {
  for (size_t i = 1; i < count; ++i) {
    if (va_arg(ap, int) > INT_MAX) {
      return 1;
    }
  }
  return 0;
}
 
int printList(size_t count, ...) {
  va_list ap; 
  va_start(ap, count);
 
  if (containsOutliers(count, ap)) {
    va_end(ap);
    return 1;
  }
 
  for (size_t i = 0; i < count; ++i) {
    printf("%d", va_arg(ap, int));
  }
 
  va_end(ap);
  return 0;
}

В этом примере средство проверки помечает прямое использование va_list переменная ap получено в качестве аргумента в containsOutliers функция.

Исправление - Копировать va_list Получено из другой функции

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

#include <cstdarg>
#include <cstdio>
#include <climits>
  
int containsOutliers(size_t count, va_list* ap) {
  va_list copiedAp;
  va_copy (copiedAp, *ap);
  
  for (size_t i = 1; i < count; ++i) {
    if (va_arg(copiedAp, int) > INT_MAX) {
      return 1;
    }
  }
  return 0;
}
 
int printList(size_t count, ...) {
  va_list ap; 
  va_start(ap, count);
 
  if (containsOutliers(count, &ap)) {
    va_end(ap);
    return 1;
  }
 
  for (size_t i = 0; i < count; ++i) {
    printf("%d", va_arg(ap, int));
  }
 
  va_end(ap);
  return 0;
}

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

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

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

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