CERT C++: EXP58-CPP

Передайте объект правильного типа к va_start

Описание

Управляйте определением

Передайте объект правильного типа к va_start.[1]

Реализация Polyspace

Это средство проверки проверки на Неправильные данные о типе передало va_start.

Примеры

развернуть все

Проблема

Неправильные данные о типе, переданные va_start, происходят когда второй аргумент va_start макрос имеет один из этих типов данных:

  • Тип данных, который изменяется при перенесении продвижению параметра по умолчанию.

    Например, char и short подвергнитесь продвижению int или unsigned int и float подвергается продвижению double. Типы int и double не изменяйтесь при продвижении параметра по умолчанию.

  • (C только), тип регистра или тип данных объявляются с register спецификатор.

  • (Только C++) тип справочных данных.

  • (Только C++) тип данных, который имеет нетривиального конструктора копии или нетривиального конструктора перемещения.

Риск

В функции variadic или функции с переменным количеством аргументов:

void multipleArgumentFunction(int someArg, short rightmostFixedArg, ...) {
    va_list myList;
    va_start(myList, rightmostFixedArg);
    ...
    va_end(myList);
}
va_start макрос инициализирует список аргументов переменной так, чтобы дополнительные аргументы к функции variadic после фиксированных параметров могли быть получены в списке. Согласно C11 и C++ 14 Стандартов, если вы используете один из отмеченных типов данных для второго аргумента va_start макрос (например, rightmostFixedArg в предыдущем примере), поведение не определено.

Если тип данных вовлекает нетривиального конструктора копии, поведение задано реализацией. Например, ли конструктор копии вызывается в вызове va_start зависит от компилятора.

Фиксация

При использовании va_start макрос, попытайтесь использовать типы int, unsigned int или double для самого правого именованного параметра функции variadic. Затем используйте этот параметр в качестве второго аргумента va_start макрос.

Например, в этом примере, самый правый именованный параметр функции variadic имеет поддерживаемый тип данных int:

void multipleArgumentFunction(int someArg, int rightmostFixedArg, ...) {
    va_list myList;
    va_start(myList, rightmostFixedArg);
    ...
    va_end(myList);
}

Чтобы избежать неопределенного и заданного реализацией поведения, минимизируйте использование функций variadic. Используйте средства проверки для MISRA C:2012 Rule 17.1 или MISRA C++:2008 Rule 8-4-1 обнаружить использование функций variadic.

Пример – неправильные типы данных для второго аргумента va_start
#include <string>
#include <cstdarg>

double addVariableNumberOfDoubles(double* weight, short num, ...) {
    double sum=0.0;
    va_list list;
    va_start(list, num);
    for(int i=0; i < num; i++) {
        sum+=weight[i]*va_arg(list, double);
    }
    va_end(list);
    return sum;
}

double addVariableNumberOfFloats(float* weight, int num, std::string s, ...) {
    float sum=0.0;
    va_list list;
    va_start(list, s);
    for(int i=0; i < num; i++) {
        sum+=weight[i]*va_arg(list, float);
    }
    va_end(list);
    return sum;
}

В этом примере средство проверки отмечает вызов va_start \in:

  • addVariableNumberOfDoubles потому что аргумент имеет, вводят short, который подвергается продвижению параметра по умолчанию int.

  • addVariableNumberOfFloats потому что аргумент имеет, вводят std::string, который имеет нетривиального конструктора копии.

Коррекция — фиксирует тип данных для второго аргумента va_start

Убедитесь что второй аргумент va_start макрос имеет поддерживаемый тип данных. В следующем откорректированном примере:

  • В addVariableNumberOfDoubles, тип данных последнего именованного параметра функции variadic изменяется на int.

  • В addVariableNumberOfFloats, вторые и третьи параметры функции variadic переключаются так, чтобы типом данных последнего именованного параметра был int.

#include <string>
#include <cstdarg>

double addVariableNumberOfDoubles(double* weight, int num, ...) {
    double sum=0.0;
    va_list list;
    va_start(list, num);
    for(int i=0; i < num; i++) {
        sum+=weight[i]*va_arg(list, double);
    }
    va_end(list);
    return sum;
}

double addVariableNumberOfFloats(double* weight, std::string s, int num, ...) {
    double sum=0.0;
    va_list list;
    va_start(list, num);
    for(int i=0; i < num; i++) {
        sum+=weight[i]*va_arg(list, double);
    }
    va_end(list);
    return sum;
}

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

Группа: 02. Выражения (EXP)
Введенный в 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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