MEM32-C. メモリ割り当てエラーを検出し、対処する
メモリ割り当て関数の返り値は、割り当てが失敗したのか成功したのかを示す。C99 によると、calloc()、malloc()、および realloc() は、要求されたメモリ割り当てが失敗すると NULL ポインタを返す [ISO/IEC9899:1999]。メモリ割り当てエラーを検出して正しく処理しないと、プログラムの予期せぬあるいは意図せぬ動作が引き起こされる可能性がある。それゆえ、メモリ割り当て関数の返り値をチェックし、エラーを適切に処理する必要がある。
次の表は、C標準のメモリ割り当て関数の考えられる戻り値を示している。
関数 成功時の戻り値 エラー時の戻り値 malloc() 割り当てられた領域へのポインタ NULL ポインタ calloc() 割り当てられた領域へのポインタ NULL ポインタ realloc() 新しいオブジェクトへのポインタ NULL ポインタ
違反コード
この例では、str が参照する動的に割り当てられたメモリ領域に input_string をコピーしている。しかし、str を参照する前に malloc() の結果をチェックしていない。この結果、malloc() が失敗した場合、プログラムは異常終了する。
char *input_string= /* 信頼できないデータで初期化 */; size_t size = strlen(input_string) + 1; char *str = (char *)malloc(size); strcpy(str, input_string); /* ... */ free(str); str = NULL;
適合コード
malloc() 関数は、他のメモリ割り当て関数と同様に、NULL ポインタまたは割り当てられたメモリ領域へのポインタのどちらかを返す。返されたポインタは必ず検査し、ポインタを参照する前にそのポインタが NULL ではないことを確認する必要がある。返されたポインタが NULL の場合、適切にエラー条件を処理すること。
char *input_string= /* 信頼できないデータで初期化 */; size_t size = strlen(input_string) + 1; char *str = (char *)malloc(size); if (str == NULL) { /* メモリ割当てエラーの処理 */ } else { strcpy(str, input_string); /* ... */ free(str); str = NULL;
違反コード
以下のコードでは、realloc() により p が参照するメモリのサイズを変更している。しかし、realloc() は失敗すると NULL ポインタを返す。この結果、元のメモリブロックと p の間の関連が切断され、メモリリークを引き起こす。
void *p; size_t new_size = /* ゼロでない値 */; p = realloc(p, new_size); if (p == NULL) { /* エラー処理 */ }
realloc() を使用する場合、ゼロバイトの割り当ての場合を考慮することが重要である (「MEM04-C. 長さゼロの割り当てを行わない」を参照)。
適合コード
以下の解決法では、realloc() の結果を、元のポインタ p に代入する前に仮のポインタ q に代入し、妥当性を確認している。
void *p; void *q; size_t new_size= /* ゼロでない値 */; q = realloc(p, new_size); if (q == NULL) { /* エラー処理Handle */ } else { p = q; }
リスク評価
割り当てエラーを検出しないと、プログラムの異常終了やサービス運用妨害(DoS)攻撃につながる可能性がある。
脆弱なプログラムが返り値からのメモリオフセットを参照した場合、攻撃者はプログラムを攻撃し任意のメモリを読み書きする可能性がある。これは、任意のコードを実行するために使用される[VU#159523]。
ルール | 深刻度 | 可能性 | 修正コスト | 優先度 | レベル |
---|---|---|---|---|---|
MEM32-C | 高 | 高 | 中 | P18 | L1 |
自動検出(最新の情報はこちら)
Fortify SCA Version 5.0 はこのルールの違反を検出できる。
Compass/ROSE はこのルールの違反を検出できる。 とくに、変数が使用される前には NULL でないかの検査が行われることを確認する。「EXP34-C. NULL ポインタを参照しないこと」を参照。
関連する脆弱性
Adobe Flash の脆弱性 [VU#159523] は、Flash が calloc() からの返り値をチェックしないことに起因する。calloc() が NULL を返したとしても、Flash は返り値であるポインタを直接使って読み書きするのではなく、ポインタ値からのオフセットに書き込もうとする。通常、NULL ポインタを参照するとプログラムはクラッシュするが、NULL からのオフセットを参照することで、クラッシュせずに脆弱性が発現する。
メトリック | ID | 公開日 | 名称 |
---|---|---|---|
38.81 | VU#159523 | 04/18/2008 | Adobe Flash Player integer overflow vulnerability |
参考情報
- [ISO/IEC 9899:1999] Section 7.20.3, "Memory management functions"
- [MITRE 07] CWE ID 476, "NULL Pointer Dereference," and CWE ID 252, "Unchecked Return Value"
- [Seacord 05] Chapter 4, "Dynamic Memory Management"
- [VU#159523]
翻訳元
これは以下のページを翻訳したものです。