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

source code of clang-tools-extra/test/clang-tidy/checkers/bugprone/signal-handler.c