信号ハンドラーでの errno の不適切な使用
信号ハンドラーで errno
を設定する関数を呼び出した後に errno
を読み取る
説明
この欠陥は、信号ハンドラーで以下のいずれかの関数が呼び出された場合に発生します。
signal
: 信号ハンドラーで関数signal
を呼び出し、次にerrno
の値を読み取ります。たとえば、信号ハンドラー関数
handler
でsignal
を呼び出し、次にerrno
を読み取るperror
を呼び出します。typedef void (*pfv)(int); void handler(int signum) { pfv old_handler = signal(signum, SIG_DFL); if (old_handler == SIG_ERR) { perror("SIGINT handler"); } }
errno
を設定する POSIX® 関数: 信号ハンドラーでerrno
を設定する POSIX 関数を呼び出しても、その信号ハンドラーから返されたときにerrno
は復元されません。たとえば、信号ハンドラー関数
handler
で、errno
を変更するwaitpid
を呼び出しても、返される前にerrno
は復元されません。#include <stddef.h> #include <errno.h> #include <sys/wait.h> void handler(int signum) { int rc = waitpid(-1, NULL, WNOHANG); if (ECHILD != errno) { } }
リスク
チェッカーによってフラグが設定される各ケースでは、errno
の不確定の値に依存するリスクがあります。
signal
:信号ハンドラーでのsignal
の呼び出しに失敗した場合、errno
の値が不確定になります (C11 規格、節 7.14.1.1).errno
の特定の値に依存すると、予期しない結果になる可能性があります。errno
を設定する POSIX 関数:errno
を設定する関数は失敗時にerrno
を設定します。信号ハンドラーが呼び出されて、その信号ハンドラー自体によりerrno
を設定する関数が呼び出された後にerrno
を読み取る場合、予期しない結果になる可能性があります。
修正方法
errno
の不確定の値に依存するリスクがある状況を回避します。
signal
: 信号ハンドラーで関数signal
を呼び出した後に、errno
を読み取ったり、errno
を読み取る関数を使用したりしないようにします。errno
を設定する POSIX 関数: 信号ハンドラーでerrno
を設定する関数を呼び出す前に、errno
を一時変数に保存します。信号ハンドラーから返される前にこの変数からerrno
を復元します。
例
結果情報
グループ: プログラミング |
言語: C | C++ |
既定値: 手書きコードはオン、生成コードはオフ |
コマンド ライン構文: SIG_HANDLER_ERRNO_MISUSE |
影響度: Medium |
バージョン履歴
R2018a で導入