JPCERT コーディネーションセンター

EXP01-C. ポインタが参照する型のサイズを求めるのにポインタのサイズを使わない

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_arrayNULL であるか初期化されていなかった場合であっても式は正しい。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

 

 

 

Klocwork

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)

Top へ

Topへ
最新情報(RSSメーリングリストTwitter