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_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 <stdarg.h>
#include <stdio.h>
#include <limits.h>
  
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 <stdarg.h>
#include <stdio.h>
#include <limits.h>
  
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;
}

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

Группа: правило 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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