Неправильный тип данных передал va_arg

Тип данных variadic аргумента функции не совпадает с типом в вызове va_arg

Описание

Неправильный тип данных передал va_arg, когда тип данных в вызове va_arg не совпадает с типом данных variadic аргумента функции, который читает va_arg.

Например, вы передаете аргумент unsigned char функции variadic func. Из-за продвижения параметра по умолчанию аргумент продвинут на int. Когда вы используете вызов va_arg, который читает аргумент unsigned char, несоответствие типов происходит.

void func (int n, ...) {
   ...   
   va_list args;
   va_arg(args, unsigned char);
   ...   
}

void main(void) {
   unsigned char c;
   func(1,c);
}

Риск

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

Чтение неправильного типа с вызовом va_arg может привести к неопределенному поведению. Поскольку аргументы функции находятся на стеке, вы можете получить доступ к нежелательной области стека.

Фиксация

Убедитесь, что тип данных аргумента, переданного функции variadic, совпадает с типом данных в вызове va_arg.

Аргументы функции variadic подвергаются продвижениям параметра по умолчанию. Типы данных аргумента функции variadic не могут быть определены от прототипа. Аргументы таких функций подвергаются продвижениям параметра по умолчанию (см. Секунду. 6.5.2.2 и 7.15.1.1 в Стандарте C99). Целочисленные аргументы подвергаются целочисленному продвижению и аргументам типа, float продвинут на double. Для целочисленных аргументов, если тип данных может быть представлен int, например, char или short, это продвинуто на int. В противном случае это продвинуто на unsigned int. Все другие аргументы не подвергаются продвижению.

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

Примеры

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

#include <stdarg.h>
#include <stdio.h>

unsigned char func(size_t count, ...) {
    va_list ap;
    unsigned char result = 0;
    va_start(ap, count);
    if (count > 0) {
        result = va_arg(ap, unsigned char);
    }
    va_end(ap);
    return result;
}

void func_caller(void) {
    unsigned char c = 0x12;
    (void)func(1, c);
}

В этом примере func берет аргумент unsigned char, который подвергается продвижению параметра по умолчанию int. Типом данных в вызове va_arg является все еще unsigned char, который не совпадает с типом аргумента int.

Исправление — использует int в качестве аргумента va_arg

Одно возможное исправление должно считать аргумент int с va_arg.

#include <stdarg.h>
#include <stdio.h>

unsigned char func(size_t count, ...) {
    va_list ap;
    unsigned char result = 0;
    va_start(ap, count);
    if (count > 0) {
        result = va_arg(ap, int); 
    }
    va_end(ap);
    return result;
}

void func_caller(void) {
    unsigned char c = 0x12;
    (void)func(1, c); 
}

Информация о результате

Группа: Программирование
Язык: C | C++
Значение по умолчанию: на
Синтаксис командной строки: VA_ARG_INCORRECT_TYPE
Влияние: носитель
ID CWE: 686

Введенный в R2018a