メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

va_list 引数が無効です

変数の引数リストが、va_end での無効化後に使用されているか、va_start または va_copy で初期化されていない

説明

この欠陥は、変数 va_listvprintf グループの関数の引数として使用する一方で、以下が該当する場合に発生します。

  • 変数が、va_start または va_copy を使用して前もって初期化されていない。

  • 変数が、va_end を使用して前もって無効化され、かつ再初期化されていない。

たとえば、関数 vsprintfvsprintf (buffer,format, args) として呼び出すとします。しかし、関数呼び出しの前に、va_list 変数 args が次のいずれによっても初期化されていません。

  • va_start(args, paramName)paramName は可変引数関数の最後の名前付き引数です。たとえば、関数定義 void func(int n, char c, ...) {} では、c が最後の名前付き引数となります。

  • va_copy(args, anotherList)anotherList は別の有効な変数 va_list です。

リスク

初期化されていない va_list 引数の動作は未定義となります。初期化されていない va_list 引数で関数を呼び出すと、スタック オーバーフローの原因となることがあります。

修正方法

va_list 変数を関数の引数として使用する前に、va_start または va_copy で初期化します。

変数の使用がすべて終了してから、va_end を使用しで変数をクリーンアップします。

すべて展開する

#include <stdarg.h>
#include <stdio.h>

int call_vfprintf(int line, const char *format, ...) {
    va_list ap;
    int r=0;
    
    va_start(ap, format);
    r = vfprintf(stderr, format, ap);
    va_end(ap);

    r += vfprintf(stderr, format, ap);
    return r;
}

この例では、va_list 変数 ap が、va_end マクロが呼び出された後に関数 vfprintf で使用されています。

修正 — va_endva_list 変数の使用後に呼び出す

1 つの修正方法として、va_list 変数の使用がすべて終了してから、はじめて va_end を呼び出します。

#include <stdarg.h>
#include <stdio.h>

int call_vfprintf(int line, const char *format, ...) {
    va_list ap;
    int r=0;
    
    va_start(ap, format);
    r = vfprintf(stderr, format, ap);
    r += vfprintf(stderr, format, ap);
    va_end(ap);
    
    return r;
}

結果情報

グループ: プログラミング
言語: C | C++
既定値: 手書きコードはオン、生成コードはオフ
コマンド ライン構文: INVALID_VA_LIST_ARG
影響度: High

バージョン履歴

R2015b で導入