C および C++ プログラマーは、特に文字列に対して、適切な境界チェックを頻繁に実行できないことで、過去 10 年ほどの間、打撃を受けてきました。これらの障害は、多くの場合、主要なソフトウェア製品に重大なセキュリティ上の問題を引き起こしています。バッファ オーバーフローの危険性が十分に理解されるようになってから、適切な境界チェックを導入しようとする動きにより、多くのプログラマが従来のバッファおよび文字列操作関数などから遠ざかりましstrcpy()
たsprintf()
。これは、これらの関数がバッファ オーバーフローの問題を引き起こす傾向があるためです。ターゲット バッファのサイズに関する仮定。std::string
や などの STL 型の利点の 1 つは、std::vector
バッファー アクセスの強力な制御です。
しかし、1つのことが私を困惑させます。C++ ヘッダーで最も広く使用されている関数の多くは、<algorithms>
オーバーフローの悪用を積極的に求めているようです。具体的にはbegin
、対応する反復子なしで反復子 (特に InputIterator)を取る関数ですend
。例えば:
template <class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result);
template <class InputIterator, class OutputIterator, class UnaryOperation>
OutputIterator transform (InputIterator first1, InputIterator last1,
OutputIterator result, UnaryOperation op);
template <class ForwardIterator1, class ForwardIterator2>
bool is_permutation (ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2);
最後の例 — <code>is_permutation() は特に有益です。copy()
とtransform()
はよく理解されているため、C++ プログラマーは、これらの関数を呼び出す前に出力コンテナーの境界を手動でチェックするか、back_inserter
必要に応じて出力コンテナーが大きくなるようにする a のようなものを使用することを知っておく必要があります。したがって、と は誤用される可能性がcopy()
ありtransform()
ますが、何でも可能であり、プログラマーはこれらのような関数のベスト プラクティスについて簡単に教育されます。
is_permutation()
はよりトリッキーなケースです。上記の関数宣言を見るだけで、2 番目の範囲 ( で始まる範囲) のサイズについてどう思いますfirst2
か? 2 番目の範囲は、最初の範囲と同じサイズである必要がありますか? これらの質問に対する簡単な答えが思い浮かばないことは間違いありません。「順列」の概念は、ほとんどのプログラマーにとって、コピーの概念ほど快適ではなく、なじみがありません。したがって、is_permutation()
間違いを犯したり、何らかの方法でバッファをオーバーフローさせたりするのは比較的簡単に思えます。
"調べる!" 私はあなたが言うことを聞きます。はい、もちろんです。しかし、プログラマーが覚えておくべきことをすべて覚えていて、他のすべてを調べていれば、バグやセキュリティ ホールは発生しないのではないでしょうか?
ではis_permutation()
、同様の関数 (つまり、すべての入力反復子を受け取るが、すべての範囲に対して完全な開始と終了の反復子のペアを取得しない関数) では、すべての入力範囲に対して完全な開始と終了のペアを必要としないのはなぜでしょうか? lexicographical_compare()
(たとえば、はこの要件を満たしていることに注意してください。) のような関数is_permutation()
は、私が想像しているほど実際には危険ではありませんか?