ITER.RANGE.INVALID
無効な反復子範囲の使用
ITER チェッカーはコンテナー内の反復子に関する問題を検出します。ITER.RANGE.INVALID チェッカーは、C++ STL アルゴリズムに渡される無効な反復子範囲にフラグを立てます。有効な範囲 [first, last) では、両方の反復子が同じコンテナーを参照しており、コンテナーのシーケンスにおいて first が last より後に位置せず、かつ、いずれの反復子も特異値でなく、その操作に対して無効でないことが必要です。
脆弱性とリスク
無効な反復子範囲を使用すると、未定義の動作を引き起こす可能性があります。逆順の範囲を指定すると、STL アルゴリズムがコンテナーの末尾を越えて反復子を進めるおそれがあります。また、異なるコンテナーに属する反復子のペアを指定すると、範囲外アクセスや終了しない反復処理が発生するおそれがあります。その結果、メモリ破損、情報漏洩、予期せぬプログラム動作などが発生する可能性があります。
軽減と防止
反復子の範囲を指定する場合は、end() よりも前に begin() を渡してください。両方の反復子が同じコンテナーインスタンスから取得されたものであることを確認し、反復子が等しい場合のみ、有効な空の範囲として使用してください。
脆弱コード例
#include <algorithm>
#include <iostream>
#include <vector>
void f(const std::vector<int> &c)
{
std::for_each(c.end(), c.begin(), [](int i) { std::cout << i; });
}
この例では、開始反復子の前に終了反復子が渡されています。アルゴリズムは、1 番目の反復子が 2 番目の反復子と一致するまでインクリメントを続けるため、終了反復子をインクリメントすると未定義の動作が発生します。
修正コード例
#include <algorithm>
#include <iostream>
#include <vector>
void f(const std::vector<int> &c)
{
std::for_each(c.begin(), c.end(), [](int i) { std::cout << i; });
}
修正された例では、反復子が正しい順序で渡されています。
脆弱コード例
#include <algorithm>
#include <iostream>
#include <vector>
void f(const std::vector<int> &c)
{
std::vector<int>::const_iterator e;
std::for_each(c.begin(), e, [](int i) { std::cout << i; });
}
この例では、2 番目の反復子がデフォルト初期化されており、コンテナー c に由来するものではありません。これら 2 つの反復子は有効な範囲を形成しないため、アルゴリズムは予期しない動作をする可能性があります。
修正コード例
#include <algorithm>
#include <iostream>
#include <vector>
void f(const std::vector<int> &c)
{
std::for_each(c.begin(), c.end(), [](int i) { std::cout << i; });
}
修正された例では、両方の反復子が同じコンテナーから取得されます。
関連チェッカー
拡張機能
該当なし