CERT.VA_ARG.TYPE
va_arg() マクロに渡される型は、デフォルト引数の昇格後に、可変個引数の関数に渡される型と一致する必要があります。 具体的には、C および C++ では、可変個の float 引数を double に昇格し、小さい整数型を int に昇格します。そのため、float 型またはいずれかの小さい整数型 (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);
}
この非準拠の例では、正しくない型が va_arg() マクロに引数として渡されるため、Klocwork は 9 行目と 20 行目で CERT.VA_ARG.TYPE の欠陥を報告します。これは、デフォルトの引数の昇格後に型「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() マクロに渡されるため、準拠しています。