Описание
Неправильный тип данных передал 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.
Пример - char, Используемый в качестве аргумента Function Argument Type и 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, 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);
}