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;
}
ヒープ上にメモリを割り当てるのではなく、スタック上にメモリを割り当ることにより、準拠コードになりました。