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

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

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