UFM.RETURN.MIGHT

解放されたメモリを指すポインターが返される場合があります

メモリが、解放後に使用または参照されるか、2 回解放されると、予想外の結果が生じる可能性があります。メモリ参照問題により、予期しない値の使用が引き起こされ、それが原因でプログラムがクラッシュしたり任意のコードが実行されたりする可能性があります。

メモリ解放後使用エラーまたはメモリの二重解放エラーは通常、エラー状況または例外、未解決の競合状態、あるいはプログラムのさまざまな部分の間でメモリの担当責任が混乱しているときに発生します。UFM チェッカーは、コードのさまざまなメモリ解放後使用またはメモリの二重解放状況のインスタンスを探します。UFM.RETURN.MIGHT チェッカーは、関数が解放されたメモリを指すポインターを返す場合がある状況にフラグを立てます。

脆弱性とリスク

メモリ参照問題は、重大な問題であることがわかることがあります。以前に解放されたメモリを使用すると、特定の状況に応じて、有効なデータが破損されるか、恣意的なコードが実行される可能性があります。メモリが解放されても、再度割り当てられるかリサイクルされないと、内容がそのまま残って、アクセスできる状態のままになる可能性があります。解放された場所にあるデータは、有効であるように思えるかもしれませんが、予想外に変化して意図しないコード動作を引き起こすことがあります。

メモリが解放されて元のポインターが再度使用された後に、メモリが別のポインターに割り当てられた場合、新しい割り当てでの場所をポイントする可能性があります。データが変化すると、有効な方法で使用されたメモリが破壊され、未定義のアクションが生じる可能性があります。関数ポインターが有効なコードのアドレスで上書きされた場合、悪意のあるユーザーが任意のコードを実行することができます。

プログラムが同じメモリを 2 回解放すると、メモリ管理データ構造が破壊され、プログラムがクラッシュしたり、2 つの後の関数呼び出しで同じポインターが返されたりすることがあります。この場合、攻撃者は二重に割り当てられたメモリに書き込まれるデータを制御できるようになることがあります。このメモリが今度は、バッファオーバーフロー攻撃に対して脆弱になります。

軽減と防止

メモリ参照問題を回避するには:

  • ポインターが解放されたら、null に設定します。
  • グローバル変数は一度しか解放されないことを確認します。
  • ループまたは条件ステートメントでメモリを解放するときおよび、realloc 関数を使用しているときは特に注意します。
  • クリーンアップルーチンがメモリ割り当てのステートを尊重していることを確認します。

脆弱コード例

コピー
  #include <stdlib.h>
 
  int *foo(int t) {
      static int *x = NULL;
      if (!x) {
          x = (int *)malloc(sizeof(int));
      }
      if (t) {
          free(x);
     }
     return x;
 }

Klocwork は 'x' によってポイントされるメモリが、9 行目で解放される可能性があり、ポインターが 11 行目で返されることを示すレポートを生成します。通常、メモリは解放されるが、この例のコードでは削除されている離れたポイントで再度使用されるので、そのような状況を認識するのは困難になります。いずれにしても、解放されたメモリを指すポインターを返すことの結果は、予測不可能で重大な結果になることがよくあります。