メインコンテンツ

CWE Rule 415

説明

ルールの説明

The product calls free() twice on the same memory address, potentially leading to modification of unexpected memory locations.

Polyspace 実装

ルール チェッカーは、"以前に割り当て解除したポインターの解放" をチェックします。

すべて展開する

問題

この問題は、メモリのブロックが、関数 free を使用して中間割り当てなしで、連続して解放された場合に発生します。

リスク

malloccalloc、または realloc を使用してポインターに動的メモリが割り当てられている場合、ポインターはヒープ上のメモリ位置を指します。このポインターに対して関数 free を使用すると、メモリの関連ブロックが再割り当て用に解放されます。メモリのこのブロックを解放しようとすると、セグメンテーション違反が発生する可能性があります。

修正方法

修正方法は欠陥の根本原因によって異なります。最初の割り当て解除と 2 番目の割り当て解除の間でメモリ ブロックをポインターに割り当てることを意図しているかどうかを確認します。そうでない場合は、2 番目の free ステータスを削除します。

メモリ ブロックを解放した後、対応するポインターに NULL を割り当てることをお勧めします。ポインターを解放する前に、NULL 値かどうかをチェックしてエラーを処理します。この方法により、既に解放されているブロックを解放するのを避けることができます。

例 — 以前に割り当て解除したポインターの解放エラー
#include <stdlib.h>

void allocate_and_free(void)
{

    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) return;

    *pi = 2;
    free(pi);
    free (pi);  //Noncompliant
    /* Defect: pi has already been freed */
}

最初の free ステートメントにより、pi が参照するメモリのブロックが解放されます。pi に対する 2 番目の free ステートメントにより、既に解放されたメモリが解放されます。

修正 — 重複する割り当て解除を削除

1 つの修正方法として、2 番目の free ステートメントを削除することができます。

#include <stdlib.h>

void allocate_and_free(void)
{

    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) return;

    *pi = 2;
    free(pi);
    /* Fix: remove second deallocation */
 }
例 — サイズがゼロの可能性のある、過去に再割り当てされたポインターの解放
#include <stdlib.h>
  
void reshape(char *buf, size_t size) {
  char *reshaped_buf = (char *)realloc(buf, size);
  if (reshaped_buf == NULL) {
    free(buf);  //Noncompliant
  }
}

この例では、関数 reshape() の引数 size がゼロになり、その結果、realloc() でサイズがゼロの再割り当てが行われる可能性があります。GNU® ライブラリなどの一部の実装では、サイズがゼロの再割り当てによってメモリが解放されると、二重解放の欠陥につながります。

修正 – サイズがゼロの再割り当てを防止する

1 つの修正方法として、使用する前に realloc() のサイズ引数の値がゼロかどうかをチェックします。サイズ引数がゼロの場合は、メモリを再割り当てするのではなく、単に解放します。

#include <stdlib.h>

void reshape(char *buf, size_t size) {
  if (size != 0) {
    char *reshaped_buf = (char *)realloc(buf, size);
    if (reshaped_buf == NULL) {
      free(buf);
    }
  }
  else {
    free(buf);
  }

}

チェック情報

カテゴリ: その他

バージョン履歴

R2023a で導入