CERT.VA_ARG.TYPE
传递给 va_arg() 宏的类型必须与默认参数提升后传递给可变参数函数的类型相匹配。 具体而言,C 和 C++ 会将可变浮点参数提升为 double,较小的整数类型则提升为 int。因此,使用浮点类型或某个较小的整数类型(例如,unsigned char、short 等等)来调用 va_arg() 是不正确的行为。
CERT.VA_ARG.TYPE 检查器会标记传递给 va_arg() 的类型与参数提升后传递给可变参数函数的类型不匹配的情况。
漏洞与风险
如果传递给 va_arg() 的类型与默认参数提升后传递给可变参数函数的类型不匹配,则会出现未定义的行为。
缓解与预防
不要通过错误类型的参数(如 short int、unsigned short int、char、unsigned char、signed char 或 float)来调用 va_arg() 宏。
漏洞代码示例
复制
#include <stdarg.h>
#include <stddef.h>
void func1(size_t num_vargs, ...)
{
va_list ap;
va_start(ap, num_vargs);
if (num_vargs > 0) {
unsigned char c = va_arg(ap, unsigned char);
// ...
}
va_end(ap);
}
void func2(size_t num_vargs, ...)
{
va_list ap;
va_start(ap, num_vargs);
if (num_vargs > 0) {
float var = va_arg(ap, float);
// ...
}
va_end(ap);
}
void f(void)
{
unsigned char c = 0x12;
float d =1.25;
func1(1, c);
func2(1, d);
}
在此不符合要求的示例中,Klocwork 在第 9 行和第 20 行报告了 CERT.VA_ARG.TYPE 缺陷,因为将错误的类型作为参数传递给 va_arg() 宏。这是因为默认参数提升后,unsigned char 类型会转换为 int,float 会转换为 double,这可能会导致未定义的行为。
修正代码示例
复制
#include <stdarg.h>
#include <stddef.h>
void func1(size_t num_vargs, ...)
{
va_list ap;
va_start(ap, num_vargs);
if (num_vargs > 0) {
unsigned char c = (unsigned char) va_arg(ap, int);
// ...
}
va_end(ap);
}
void func2(size_t num_vargs, ...)
{
va_list ap;
va_start(ap, num_vargs);
if (num_vargs > 0) {
double var1 = va_arg(ap, double);
// ...
}
va_end(ap);
}
void f(void)
{
int i = 10;
double d = 10.234;
func1(1, i);
func2(1, d);
}
以上代码符合要求,因为将正确的类型(如 int 或 double)传递给 va_arg() 宏。