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

EXP44-C. sizeof 演算子のオペランドは副作用を持たせない

sizeof 演算子の結果は、そのオペランドのサイズ(バイト)とする。オペランドは、式または括弧で囲まれた型の名前のいずれかとする。オペランドの型が可変長配列型 (VLA) である場合は式が評価され、この型でない場合はオペランドは評価されない。

sizeof 演算子のオペランドの部分が VLA 型で、VLA のサイズの値を変更しても演算子の結果に影響しない場合、サイズが評価されるかどうかは指定されない。C 標準の附属書 J、セクション J.1 の「未規定の動作」の 22 を参照すること [ISO/IEC 9899:2011]。

副作用を生成するような式は、VLA 以外の場合にそのような式が評価されず、未規定の結果が発生するということを知らないプログラマに混乱を与える恐れがある。その結果、プログラマはプログラムの実行状態について誤った仮定をしてしまい、エラーやソフトウェアの脆弱性につながる恐れがある。

違反コード

以下のコード例では、式 a++ は評価されず、式中の副作用は実行されない。

int a = 14;
int b = sizeof(a++);

したがって、b が初期化された後の a の値は 14 である。

処理系固有の詳細

このコード例は Microsoft Visual Studio 2005 Version 8.0 に /W4 オプションをつけてコンパイルすると警告はでない。

適合コード

以下の適合コードでは、変数 a をインクリメントしている。

int a = 14;
int b = sizeof(a);
a++;
違反コード (可変長配列)

以下のコード例では、a の初期化における式 ++n は、sizeof 演算子の VLA オペランドのサイズに影響を及ぼすため、評価する必要がある。しかし、n の値に関係なく式 ++n % 10 となるため、この値は sizeof 演算子の結果に影響しない。そのため、n がインクリメントされるかどうかは指定されない。

void f(size_t n) {
  size_t a = sizeof(int [++n]);           /* n のインクリメントが必要 */
  size_t b = sizeof(int [++n % 1 + 1]);   /* n のインクリメントは不要 */
  /* ... */
}
適合コード (可変長変数)

以下のコード例では、sizeof 式で使用される変数 n の値は変更せず、代わりに外部で安全にインクリメントしている。

void f(size_t n) {
  size_t a = sizeof(int [n + 1]);
  ++n;

  size_t b = sizeof(int [n % 1 + 1]);
  ++n;
  /* ... */
}
リスク評価

副作用を生成するようにみえる式を sizeof 演算子に渡すと、結果は期待した値と異なるかもしれない。結果の値の利用如何によっては、意図せぬプログラムの動作につながる恐れがある。

ルール

深刻度

可能性

修正コスト

優先度

レベル

EXP44-C

P3

L3

自動検出

ツール

バージョン

チェッカー

説明

Compass/ROSE

 

 

 

ECLAIR

1.1

unexfct

実装済み

       

LDRA tool suite

V. 8.5.4

54 S

実装済み

PRQA QA-C 8.1 3307 実装済み
関連するガイドライン
CERT C++ Secure Coding Standard EXP06-CPP. Operands to the sizeof operator should not contain side effects
CERT C++ Secure Coding Standard EXP06-CPP. Operands to the sizeof operator should not contain side effects
翻訳元

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

EXP44-C. Operands to the sizeof operator should not contain side effects (revision 58)

Top へ

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