Описание
Неправильный тип данных передал 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);
}