MEM07-C. calloc() の引数は乗算した結果がラップアラウンドしないようにする
calloc()
関数は、割り当てる要素の数と、各要素の記憶域サイズの2つを引数に取る。一般に、calloc()
の実装は2つの引数を乗算し、割り当てるメモリ量を決定する。過去には、乗算結果がラップアラウンドしないかどうかを検査していない実装もあった [RUS-CERT Advisory 2002-08:02]。割り当てる要素の数と記憶域のサイズを乗算した結果がラップアラウンドする場合、割り当てられるメモリは要求しているよりも少なくなる。そのため、これらの引数を乗算した時にラップアラウンドしないことを保証する必要がある。
最近の標準Cライブラリ実装では、ラップアラウンドの検査を行っているはずである。乗算における符号無し整数のラップアラウンドに適切に対処しているライブラリであれば、このレコメンデーションに適合している。
違反コード
以下のコード例では、ユーザ定義関数 get_size()
(ここには示されていない)を使用して long int
型の動的配列に必要なサイズを計算し、変数 num_elements
に代入しているものとする。calloc()
がバッファを割り当てる際に、num_elements
と sizeof(long)
の乗算が行われ、必要な合計サイズが計算される。要素数とサイズの乗算結果が size_t
型で表現できないほど大きい場合、(実際にはラップアラウンドした値が使われることになり、) calloc()
が割り当てるバッファのサイズは要求されたよりも小さいものとなる。このバッファにデータがコピーされると、オーバーフローが発生する。
size_t num_elements; long *buffer = (long *)calloc(num_elements, sizeof(long)); if (buffer == NULL) { /* エラー条件の処理 */ } /*...*/ free(buffer); buffer = NULL;
適合コード
以下の適合コードでは、calloc()
を呼び出す前に、2つの引数 num_elements
と sizeof(long)
についてラップアラウンドが生じるかどうかを検査している。
long *buffer; size_t num_elements; if (num_elements > SIZE_MAX/sizeof(long)) { /* エラー条件の処理 */ } buffer = (long *)calloc(num_elements, sizeof(long)); if (buffer == NULL) { /* エラー条件の処理 */ }
割り当て可能なメモリの最大量は通常、SIZE_MAX
(size_t
の最大値)未満に制限される。「MEM32-C. メモリ割り当てエラーを検出し、対処する」に適合するために、メモリ割り当て関数の返り値は必ずチェックすること。
リスク評価
メモリ割り当て関数の内部で符号無し整数のラップアラウンドが発生すると、バッファオーバーフローを引き起こし、それが攻撃者によって悪用されると、脆弱性のあるプロセスの権限を使った任意のコード実行につながる可能性がある。最近の calloc()
の実装であればたいていの場合、ラップアラウンドが発生しないか検査しているだろうが、使用している calloc()
が安全なバージョンであると想定するのは危険である。とくに、動的にリンクされたライブラリを使用している場合には、注意せよ。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
MEM07-C |
高 |
低 |
中 |
P6 |
L2 |
自動検出(最新の情報はこちら)
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
Compass/ROSE |
|
|
|
関連するガイドライン
CERT C++ Secure Coding Standard | MEM07-CPP. Ensure that the arguments to calloc(), when multiplied, can be represented as a size_t |
MITRE CWE | CWE-190, Integer overflow (wrap or wraparound) CWE-128, Wrap-around error |
参考資料
[RUS-CERT] | Advisory 2002-08:02, "Flaw in calloc and Similar Routines" |
[Seacord 2013] | Chapter 4, "Dynamic Memory Management" |
[Secunia] | Advisory SA10635, "HP-UX calloc Buffer Size Miscalculation Vulnerability" |
翻訳元
これは以下のページを翻訳したものです。
MEM07-C. Ensure that the arguments to calloc(), when multiplied, do not wrap (revision 80)