1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
|
// RUN: %check_clang_tidy %s bugprone-signal-handler %t -- -- -isystem %clang_tidy_headers
#include "signal.h"
#include "stdlib.h"
#include "stdio.h"
#include "system-other.h"
// The function should be classified as standard function even if there is
// declaration the in source file.
// FIXME: The detection works only if the first declaration is in system
// header.
int printf(const char *, ...);
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
void f_extern(void);
void f_extern_handler(int);
void handler_printf(int) {
printf("1234");
// CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_printf' registered here as signal handler
}
void test_printf(void) {
signal(SIGINT, handler_printf);
}
void handler_extern(int) {
f_extern();
// CHECK-NOTES: :[[@LINE-1]]:3: warning: cannot verify that external function 'f_extern' is asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_extern' registered here as signal handler
}
void test_extern(void) {
signal(SIGINT, handler_extern);
}
void f_ok(void) {
abort();
}
void handler_ok(int) {
f_ok();
}
void test_ok(void) {
signal(SIGINT, handler_ok);
}
void f_bad(void) {
printf("1234");
// CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE+5]]:3: note: function 'f_bad' called here from 'handler_bad'
// CHECK-NOTES: :[[@LINE+8]]:18: note: function 'handler_bad' registered here as signal handler
}
void handler_bad(int) {
f_bad();
}
void test_bad(void) {
signal(SIGINT, handler_bad);
}
void f_bad1(void) {
printf("1234");
// CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE+6]]:3: note: function 'f_bad1' called here from 'f_bad2'
// CHECK-NOTES: :[[@LINE+9]]:3: note: function 'f_bad2' called here from 'handler_bad1'
// CHECK-NOTES: :[[@LINE+13]]:18: note: function 'handler_bad1' registered here as signal handler
}
void f_bad2(void) {
f_bad1();
}
void handler_bad1(int) {
f_bad2();
f_bad1();
}
void test_bad1(void) {
signal(SIGINT, handler_bad1);
}
void handler_abort(int) {
abort();
}
void handler_signal(int) {
// FIXME: It is only OK to call signal with the current signal number.
signal(0, SIG_DFL);
}
void handler_false_condition(int) {
if (0)
printf("1234");
// CHECK-NOTES: :[[@LINE-1]]:5: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_false_condition' registered here as signal handler
}
void test_false_condition(void) {
signal(SIGINT, handler_false_condition);
}
void handler_multiple_calls(int) {
f_extern();
// CHECK-NOTES: :[[@LINE-1]]:3: warning: cannot verify that external function 'f_extern' is asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE+9]]:18: note: function 'handler_multiple_calls' registered here as signal handler
printf("1234");
// CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE+6]]:18: note: function 'handler_multiple_calls' registered here as signal handler
f_extern();
// first 'f_extern' call found only
}
void test_multiple_calls(void) {
signal(SIGINT, handler_multiple_calls);
}
void f_recursive(void);
void handler_recursive(int) {
f_recursive();
printf("");
// first 'printf' call (in f_recursive) found only
}
void f_recursive(void) {
f_extern();
// CHECK-NOTES: :[[@LINE-1]]:3: warning: cannot verify that external function 'f_extern' is asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-8]]:3: note: function 'f_recursive' called here from 'handler_recursive'
// CHECK-NOTES: :[[@LINE+9]]:18: note: function 'handler_recursive' registered here as signal handler
printf("");
// CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE-12]]:3: note: function 'f_recursive' called here from 'handler_recursive'
// CHECK-NOTES: :[[@LINE+5]]:18: note: function 'handler_recursive' registered here as signal handler
handler_recursive(2);
}
void test_recursive(void) {
signal(SIGINT, handler_recursive);
}
void f_multiple_paths(void) {
printf("");
// CHECK-NOTES: :[[@LINE-1]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]
// CHECK-NOTES: :[[@LINE+5]]:3: note: function 'f_multiple_paths' called here from 'handler_multiple_paths'
// CHECK-NOTES: :[[@LINE+9]]:18: note: function 'handler_multiple_paths' registered here as signal handler
}
void handler_multiple_paths(int) {
f_multiple_paths();
f_multiple_paths();
}
void test_multiple_paths(void) {
signal(SIGINT, handler_multiple_paths);
}
void handler_function_pointer(int) {
void (*fp)(void) = f_extern;
// Call with function pointer is not evalauted by the check.
(*fp)();
}
void test_function_pointer(void) {
signal(SIGINT, handler_function_pointer);
}
void test_other(void) {
signal(SIGINT, handler_abort);
signal(SIGINT, handler_signal);
signal(SIGINT, _Exit);
signal(SIGINT, other_call);
// CHECK-NOTES: :[[@LINE-1]]:18: warning: standard function 'other_call' may not be asynchronous-safe; using it as a signal handler may be dangerous [bugprone-signal-handler]
signal(SIGINT, f_extern_handler);
// CHECK-NOTES: :[[@LINE-1]]:18: warning: cannot verify that external function 'f_extern_handler' is asynchronous-safe; using it as a signal handler may be dangerous [bugprone-signal-handler]
signal(SIGINT, SIG_IGN);
signal(SIGINT, SIG_DFL);
}
|