JPCERT コーディネーションセンター

PRE32-C. 関数形式マクロの呼出しのなかで前処理指令を使用しない

マクロに渡す引数に #define#ifdef#include などの前処理指令を含めてはならない。C言語規格[ISO/IEC 9899:2011] セクション6.10.3 パラグラフ11によると、このようなコードは未定義の動作となる。

最も外側の括弧によって囲まれた前処理字句の列は、関数形式マクロの実引数の並びを形成する。並びの中の個々の実引数は、コンマ前処理字句によって区切る。ただし、内側に対をなす括弧がある場合、その中のコンマ前処理字句は、実引数を区切るものではない。実引数の並びの中に、ほかの場合であれば前処理指令として働く前処理字句がある場合、その動作は未定義とする。

C言語規格の附属書J、未定義動作93も参照。

このルールは、マクロにより実装されているかどうか不明な関数の引数内で使われている前処理指令にも適用される。たとえば、memcpy()printf()assert() などの標準ライブラリ関数はマクロとして実装されている可能性がある。

違反コード

以下の違反コード例 [GCC Bugs] では、memcpy() にプラットフォーム固有の引数を指定するために、前処理指令を使用している。しかし、memcpy() がマクロにより実装されていた場合、このコードは未定義の動作となる。

#include <string.h>

void func(const char *src) {
  /* ソース文字列を検証しサイズを計算 */
  char *dest;
  /* コピー先文字列のために malloc() */
  memcpy(dest, src,
    #ifdef PLATFORM1
      12
    #else
      24
    #endif
  );
  /* ... */
}
適合コード

次の適合コード [GCC Bugs] では、適切な memcpy() 呼び出しの判定を行っている。

#include <string.h>

void func(const char *src) {
  /* ソース文字列を検証しサイズを計算 */
  char *dest;
  /* コピー先文字列のために malloc() */
  #ifdef PLATFORM1
    memcpy(dest, src, 12);
  #else
    memcpy(dest, src, 24);
  #endif
  /* ... */
}
リスク評価

マクロの引数に前処理指令が含まれていると未定義の動作となる。

ルール

深刻度

可能性

修正コスト

優先度

レベル

PRE32-C

P2

L3

自動検出

ツール

バージョン

チェッカー

説明

Astrée
18.10
macro-argument-hash 実装済み
Axivion Bauhaus Suite

6.9.0

CertC-PRE32 実装済み
CodeSonar
5.0p0
LANG.PREPROC.MACROARG マクロ引数中の前処理指令

ECLAIR

1.2

CC2.PRE32

実装済み

LDRA tool suite
9.7.1
341 S 実装済み
Parasoft C/C++test

10.4.1

CERT_C-PRE32-a
Arguments to a function-like macro shall not contain tokens that look like preprocessing directives

Polyspace Bug Finder

R2018a

Preprocessor directive in macro argument You use a preprocessor directive in the argument to a function-like macro
PRQA QA-C
9.5
0853
PRQA QA-C++

4.3

1072 


RuleChecker
18.10
macro-argument-hash Fully checked
参考資料
[GCC Bugs] "Non-bugs"
[ISO/IEC 9899:2011] 6.10.3, "Macro Replacement"
翻訳元

これは以下のページを翻訳したものです。

PRE32-C. Do not use preprocessor directives in invocations of function-like macros (revision 76)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter