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() 宏。

相关检查器

外部指导