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

MSC21-C. ループの終了条件には適切な条件式を使う

MSC21-C. ループの終了条件には適切な条件式を使う

C言語では、関係演算子として<><=>=が用意されている。また、等価演算子としては==!=が用意されている。

for文やwhile文でループカウンタを使用する場合、条件式には等価演算子 != を用いるよりも、< などの関係演算子を用いる方が安全である。

違反コード (等価演算子)

以下のコード例では反復処理を5回行うように見えるが、実際にはループは終了しない。

size_t i;
for (i = 1; i != 10; i += 2) {
  /* ... */
}
適合コード (関係演算子)

関係演算子 <= を用いることで、ループは確実に終了する。

size_t i;
for (i = 1; i <= 10; i += 2 ) {
  /* ... */
}
違反コード (等価演算子)

また、ループカウンタの初期値と終了値が変数で与えられる場合、ループが確実に終了するよう注意する必要がある。以下の関数では begin < end が真であると仮定しており、そうでない場合には無限ループになる。

void f(size_t begin, size_t end) {
  size_t i;
  for (i = begin; i != end; ++i) {
    /* ... */
  }
}
適合コード (関係演算子)

この場合も、等価演算子ではなく関係演算子を用いることでループが終了することを保証できる。begin >= endが真の場合、ループの本体は実行されない。

void f(size_t begin, size_t end) {
  size_t i;
  for (i = begin; i < end; ++i) {
    /* ... */
  }
}
違反コード (境界条件)

SIZE_MAXとの比較を行う条件式など、ある型で表現できる最大値もしくは最小値との比較を行う場合、必ずしもループを終了しないことがある。

void f(size_t begin, size_t step) {
  size_t i;
  for (i = begin; i <= SIZE_MAX; i += step) {
    /* ... */
  }
}
適合コード (境界条件)

以下の適合コードでは、ある型で表現できる最大値とインクリメントする値との差分を、ループカウンタと比較している。

void f(size_t begin, size_t step) {
  if (0 < step) {
    size_t i;
    for (i = begin; i <= SIZE_MAX - step; i += step) {
      /* ... */
    }
  }
}
例外

MSC21-C-EX1: ループの繰り返しごとにループカウンタが+1され、ループ開始時のループカウンタの値がループ終了時の値より小さいもしくは等しいことが事前に分かっているなら、ループの終了条件式に等価演算子を用いてもよい。同様に、繰り返しごとにループカウンタが-1され、ループ開始時のループカウンタの値がループ終了時の値よりも大きいもしくは等しいなら、ループの終了条件式に等価演算子を用いてもよい。

size_t i;
for (i = 1; i != 5; ++i) {
  /* ... */
}
リスク評価

等価演算子による判定は、ループの終了に予想以上に時間がかかったり、ループがまったく終了しないというリスクを伴う。

レコメンデーション

深刻度

可能性

修正コスト

優先度

レベル

MSC21-C

P3

L3

自動検出(最新の情報はこちら

ツール

バージョン

チェッカー

説明

Astrée
24.04

Supported: Astrée reports potential infinite loops.
CodeSonar
8.1p0

LANG.STRUCT.LOOP.HR
LANG.STRUCT.LOOP.UB

High risk loop
Potential unbounded loop

Compass/ROSE




LDRA tool suite
9.7.1
510 S Partially implemented
PC-lint Plus

1.4

440, 442, 443,
444, 445, 2650

Partially supported

Polyspace Bug Finder

R2024a

CERT C: Rec. MSC21-C


Checks for loop bounded with tainted value (rec. partially covered)


PVS-Studio

7.31

V621
関連ガイドライン
SEI CERT C++ Coding Standard VOID MSC21-CPP. Use inequality to terminate a loop whose counter changes by more than one
CERT Oracle Secure Coding Standard for Java MSC54-J. Avoid inadvertent wrapping of loop counters
翻訳元

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

MSC21-C. Use robust loop termination conditions (revision 63)

Top へ

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