CERT.SIG.SIG_HANDLER.SHARED_OBJ.HEAP

シグナルハンドラー内で共有オブジェクトにアクセスしない

このチェッカーは、モダンエンジンにのみ適用されます。

チェッカー CERT.SIG.SIG_HANDLER.SHARED_OBJ.HEAP は、シグナルハンドラー内のすべてのヒープアクセスを検出します。

このチェッカーは、シグナルハンドラーがヒープでデータを割り当て/割り当て解除する場合にトリガーされます。これには、以下のものの使用が含まれます。

  • C++ 演算子
    • new
    • delete
  • C 関数
    • malloc
    • calloc
    • realloc
    • free
  • 割り当て関数
    • std::allocator::allocate

    • std::allocator::deallocate

脆弱性とリスク

シグナルハンドラー内で共有オブジェクトへのアクセスや変更を行うと、競合状態が発生し、データが不整合なままになる可能性があります。この規則の 2 つの例外 (C 規格 5.1.2.3 第 5 段落) は、ロックフリーのアトミック型オブジェクトおよび volatile sig_atomic_t 型の変数に対する読み取りおよび書き込み機能です。シグナルハンドラーから他の型のオブジェクトへのアクセスは未定義の動作です。

軽減と防止

シグナルハンドラー内では、ヒープに対するアクセスや割り当てを行わないでください。

脆弱コード例

コピー
#include <signal.h>
#include <stdlib.h>
#include <string.h>

enum { MAX_MSG_SIZE = 24 };
char *err_msg;

void handler(int signum) {
  char* err_msg_copy = (char *)malloc(MAX_MSG_SIZE);
}

int main(void) {
  signal(SIGINT, handler);

  err_msg = (char *)malloc(MAX_MSG_SIZE);
  if (err_msg == NULL) {
    /* Handle error */
  }
  strcpy(err_msg, "No errors yet.");
  /* Main code loop */
  return 0;
}

シグナルハンドラー内に malloc への呼び出しがあるため、このコードは非準拠です。

修正コード例

コピー
#include <signal.h>
#include <stdlib.h>
#include <string.h>

enum { MAX_MSG_SIZE = 24 };
char *err_msg;

void handler(int signum) {
  char err_msg_copy[MAX_MSG_SIZE];
}

int main(void) {
  signal(SIGINT, handler);

  err_msg = (char *)malloc(MAX_MSG_SIZE);
  if (err_msg == NULL) {
    /* Handle error */
  }
  strcpy(err_msg, "No errors yet.");
  /* Main code loop */
  return 0;
}

ヒープ上にメモリを割り当てるのではなく、スタック上にメモリを割り当ることにより、準拠コードになりました。