EXP01-C. ポインタが参照する型のサイズを求めるのにポインタのサイズを使わない
ある型のサイズを求める際に、その型へのポインタのサイズを使わないこと。ある型へのポインタのサイズは、常にそのポインタのサイズを返すのであって、その型のサイズではない。
これが問題になりうるのは、配列のサイズを求めるときである。(「ARR01-C. 配列のサイズを求める際に sizeof 演算子をポインタに適用しない」を参照。)
違反コード
以下のコード例では、sizeof()
演算子を double
型である *d_array
ではなく、誤って変数 d_array
(double
へのポインタとして宣言されている)に対して呼び出している。
double *allocate_array(size_t num_elems) { double *d_array; if (num_elems > SIZE_MAX/sizeof(d_array)) { /* エラー条件の処理 */ } d_array = (double *)malloc(sizeof(d_array) * num_elems); if (d_array == NULL) { /* エラー条件の処理 */ } return d_array; }
num_elems
の値を評価することで、式 sizeof(d_array) * num_elems
が整数オーバーフローを引き起こさないことを保証している。(「INT32-C. 符号付き整数演算がオーバーフローを引き起こさないことを保証する」を参照。)
多くの処理系では、ポインタのサイズと double
(あるいは他のすべての型) のサイズは異なる可能性が高い。たとえば IA-32 処理系では、sizeof(*double)
は4であり、sizeof(double)
は8である。この場合、double
型の100個の値を持つ配列を割り当てるには不十分な領域が確保されてしまう。
適合コード
集成型データ構造に含まれる要素のサイズは正しく計算すること。式 sizeof(*d_array)
は d_array
が参照するデータ構造のサイズを返すのであって、ポインタのサイズではない。また、ポインタ d_array
が NULL
であるか初期化されていなかった場合であっても式は正しい。sizeof
演算子はその引数の型に対して演算を行うからだ。
double *allocate_array(size_t num_elems) { double *d_array; if (num_elems > SIZE_MAX/sizeof(*d_array)) { /* エラー条件の処理 */ } d_array = (double *)malloc(sizeof(*d_array) * num_elems); if (d_array == NULL) { /* エラー条件の処理 */ } return d_array; }
リスク評価
実際の型ではなくポインタのサイズを使うと、不十分な領域が確保されることになり、結果としてバッファオーバーフローにつながり、攻撃者により任意のコードを実行されるおそれがある。
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
EXP01-C |
高 |
中 |
中 |
P12 |
L1 |
自動検出
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
Compass/ROSE |
|
|
|
V. 9.1 |
INCORRECT.ALLOC_SIZE |
|
|
LDRA tool suite |
V. 8.5.4 |
577 S |
実装済み |
Splint |
V. 3.1.1 |
|
|
関連するガイドライン
CERT C++ Secure Coding Standard | EXP01-CPP. Do not take the size of a pointer to determine the size of the pointed-to type |
ISO/IEC TS 17961 (ドラフト) | Taking the size of a pointer to determine the size of the pointed-to type [sizeofptr] |
MITRE CWE | CWE-467, Use of sizeof() on a pointer type |
参考資料
[Drepper 2006] | Section 2.1.1, "Respecting Memory Bounds" |
[Viega 2005] | Section 5.6.8, "Use of sizeof() on a pointer type" |
翻訳元
これは以下のページを翻訳したものです。
EXP01-C. Do not take the size of a pointer to determine the size of the pointed-to type (revision 73)