CERT.STDLIB.SIGNAL
从 SIGFPE、SIGBUS、SIGSEGV、SIGILL、SIGEMT 或 SIGTRAP 的计算异常信号处理程序返回会导致未定义的行为。
CERT.STDLIB.SIGNAL 检查器会标记从 SIGFPE、SIGBUS、SIGSEGV、SIGILL、SIGEMT 和 SIGTRAP 的计算异常信号处理程序返回的情况。 此检查器会将所有带任何指定信号类型的 signal() 调用标记为缺陷。因此,此缺陷的含义是应该检查该代码行,并非表示它一定是缺陷。
漏洞与风险
如果程序从计算异常信号处理程序返回,则会出现未定义的行为。
缓解与预防
如果信号是计算错误的结果,如 SIGFPE、SIGBUS,、SIGSEGV、SIGILL、SIGEMT 或 SIGTRAP,则不要从信号处理程序返回。
漏洞代码示例
复制
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
volatile sig_atomic_t denom;
void sighandle(int s)
{
if (denom == 0) {
denom = 1;
}
}
int main(int argc, char *argv[])
{
if (argc < 2) {
return 0;
}
char *end = NULL;
long temp = strtol(argv[1], &end, 10);
if (end == argv[1] || 0 != *end ||
((LONG_MIN == temp || LONG_MAX == temp) && errno == ERANGE)) {
/* Handle error */
}
denom = (sig_atomic_t)temp;
signal(SIGFPE, sighandle);
long result = 100 / (long)denom;
return 0;
}
在此不符合要求的示例中,Klocwork 在第 31 行报告了 CERT.STDLIB.SIGNAL 缺陷,因为该程序从计算信号处理程序返回,这属于未定义的行为。 如果输入 0,并且即使在使用信号处理程序(带信号 SIGFPE)修复错误状况后,上述程序仍未执行预期行为,则此不符合要求的代码示例将无限循环。
修正代码示例
复制
#include <errno.h>
#include <limits.h>
#include <signal.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc < 2) {
return 0;
}
char *end = NULL;
long denom = strtol(argv[1], &end, 10);
if (end == argv[1] || 0 != *end ||
((LONG_MIN == denom || LONG_MAX == denom) && errno == ERANGE)) {
/* Handle error */
}
long result = 100 / denom;
return 0;
}
以上代码符合要求,因为该程序未从 SIGFPE 处理程序返回,而是调用了 abort ()、quick_exit() 或退出函数。
相关检查器
- MISRA.STDLIB.SIGNAL