MEM08-C. realloc() は動的に割り当てられた配列のサイズ変更にのみ使用する
C 標準 [ISO/IEC 9899:2011] セクション 7.22.3.5 は、realloc(ptr, size)
関数を以下のように定めている。
ptr
が指す古いオブジェクトを解放し、大きさがsize
である新しいオブジェクトへのポインタを返す。新しいオブジェクトの内容は、新しいオブジェクトの大きさと古いオブジェクトの大きさのうち小さい方の大きさまでの部分で、解放する前の古いオブジェクトの内容と同じでなければならない。古いオブジェクトの大きさを超えた部分の新しいオブジェクトのバイトの値は、不定とする。
違反コード
以下のコード例では、realloc()
を使用して特定の型のオブジェクトに記憶域を割り当てているが、あたかも別の型のオブジェクトであるかのように初期化している。
#include <stdlib.h> typedef struct gadget gadget; struct gadget { int i; double d; char *p; }; typedef struct widget widget; struct widget { char *q; int j; double e; }; gadget *gp; widget *wp; /* ... */ wp = (widget *)realloc(gp, sizeof(widget));
このコード例では、realloc()
は widget
用に記憶域を割り当てているが、widget
の型があたかも gadget
の型であるかのように初期化している。これにより、char *
から int
、または int
から char *
への暗黙的な変換が行われるだろう。場合によっては、ポインタの値で double
を初期化することも考えられる。
適合コード
プログラムで realloc()
を使用するのは、動的に割り当てた配列のサイズを変更する場合に限るべきである。1 つの配列を、以下の適合コードに示すように、サイズは異なるが同じ型の要素を持つ別の配列として再割り当てすることができる。
#include <stdlib.h> typedef struct widget widget; struct widget { char *q; int j; double e; }; widget *wp; widget *wq; /* ... */ wp = (widget *)malloc(10 * sizeof(widget)); /* ... */ wq = (widget *)realloc(wp, 20 * sizeof(widget)); /* ... */ wp = (widget *)realloc(wq, 15 * sizeof(widget));
このプログラムは malloc()
を呼び出し、10個の widget
からなる配列に記憶域を割り当てる。その後、realloc()
を呼び出し、この配列のサイズを 20 個の widget
の配列に変更している。さらにその後、realloc()
を再度呼び出して、配列のサイズを 15 個の widget
に縮小している。
リスク評価
動的に割り当てられた配列以外のオブジェクトの記憶域のサイズを変更すると、互換性のないデータ型に暗黙的に変換されることがある。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
MEM08-C |
高 |
高 |
中 |
P18 |
L1 |
自動検出
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
Compass/ROSE |
|
|
|
ECLAIR | 1.1 | funcalls | realloc() のポインタ引数の型がキャストの型と一致しているかを確認することで、このレコメンデーションの違反を検出できる。 |
関連するガイドライン
ISO/IEC TR 24772:2013 | Type-breaking Reinterpretation of Data [AMV] |
MITRE CWE | CWE-628, Function call with incorrectly specified arguments |
参考資料
[[ISO/IEC 9899:2011] | Section 7.22.3.5, "The realloc Function" |
翻訳元
これは以下のページを翻訳したものです。
MEM08-C. Use realloc() only to resize dynamically allocated arrays (revision 47)