189a1d03eSRichard // RUN: %check_clang_tidy %s bugprone-signal-handler %t -- -- -isystem %clang_tidy_headers
289a1d03eSRichard
389a1d03eSRichard #include "signal.h"
489a1d03eSRichard #include "stdlib.h"
589a1d03eSRichard #include "stdio.h"
689a1d03eSRichard #include "system-other.h"
789a1d03eSRichard
889a1d03eSRichard // The function should be classified as standard function even if there is
989a1d03eSRichard // declaration the in source file.
1089a1d03eSRichard // FIXME: The detection works only if the first declaration is in system
1189a1d03eSRichard // header.
1289a1d03eSRichard int printf(const char *, ...);
1389a1d03eSRichard typedef void (*sighandler_t)(int);
1489a1d03eSRichard sighandler_t signal(int signum, sighandler_t handler);
1589a1d03eSRichard
1689a1d03eSRichard void f_extern(void);
17af01f717SAaron Ballman void f_extern_handler(int);
1889a1d03eSRichard
handler_printf(int)1989a1d03eSRichard void handler_printf(int) {
2089a1d03eSRichard printf("1234");
2189a1d03eSRichard // 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]
2289a1d03eSRichard // CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_printf' registered here as signal handler
2389a1d03eSRichard }
2489a1d03eSRichard
test_printf(void)2589a1d03eSRichard void test_printf(void) {
2689a1d03eSRichard signal(SIGINT, handler_printf);
2789a1d03eSRichard }
2889a1d03eSRichard
handler_extern(int)2989a1d03eSRichard void handler_extern(int) {
3089a1d03eSRichard f_extern();
3189a1d03eSRichard // 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]
3289a1d03eSRichard // CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_extern' registered here as signal handler
3389a1d03eSRichard }
3489a1d03eSRichard
test_extern(void)3589a1d03eSRichard void test_extern(void) {
3689a1d03eSRichard signal(SIGINT, handler_extern);
3789a1d03eSRichard }
3889a1d03eSRichard
f_ok(void)3989a1d03eSRichard void f_ok(void) {
4089a1d03eSRichard abort();
4189a1d03eSRichard }
4289a1d03eSRichard
handler_ok(int)4389a1d03eSRichard void handler_ok(int) {
4489a1d03eSRichard f_ok();
4589a1d03eSRichard }
4689a1d03eSRichard
test_ok(void)4789a1d03eSRichard void test_ok(void) {
4889a1d03eSRichard signal(SIGINT, handler_ok);
4989a1d03eSRichard }
5089a1d03eSRichard
f_bad(void)5189a1d03eSRichard void f_bad(void) {
5289a1d03eSRichard printf("1234");
5389a1d03eSRichard // 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]
5489a1d03eSRichard // CHECK-NOTES: :[[@LINE+5]]:3: note: function 'f_bad' called here from 'handler_bad'
5589a1d03eSRichard // CHECK-NOTES: :[[@LINE+8]]:18: note: function 'handler_bad' registered here as signal handler
5689a1d03eSRichard }
5789a1d03eSRichard
handler_bad(int)5889a1d03eSRichard void handler_bad(int) {
5989a1d03eSRichard f_bad();
6089a1d03eSRichard }
6189a1d03eSRichard
test_bad(void)6289a1d03eSRichard void test_bad(void) {
6389a1d03eSRichard signal(SIGINT, handler_bad);
6489a1d03eSRichard }
6589a1d03eSRichard
f_bad1(void)6689a1d03eSRichard void f_bad1(void) {
6789a1d03eSRichard printf("1234");
6889a1d03eSRichard // 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]
6989a1d03eSRichard // CHECK-NOTES: :[[@LINE+6]]:3: note: function 'f_bad1' called here from 'f_bad2'
7089a1d03eSRichard // CHECK-NOTES: :[[@LINE+9]]:3: note: function 'f_bad2' called here from 'handler_bad1'
7189a1d03eSRichard // CHECK-NOTES: :[[@LINE+13]]:18: note: function 'handler_bad1' registered here as signal handler
7289a1d03eSRichard }
7389a1d03eSRichard
f_bad2(void)7489a1d03eSRichard void f_bad2(void) {
7589a1d03eSRichard f_bad1();
7689a1d03eSRichard }
7789a1d03eSRichard
handler_bad1(int)7889a1d03eSRichard void handler_bad1(int) {
7989a1d03eSRichard f_bad2();
8089a1d03eSRichard f_bad1();
8189a1d03eSRichard }
8289a1d03eSRichard
test_bad1(void)8389a1d03eSRichard void test_bad1(void) {
8489a1d03eSRichard signal(SIGINT, handler_bad1);
8589a1d03eSRichard }
8689a1d03eSRichard
handler_abort(int)8789a1d03eSRichard void handler_abort(int) {
8889a1d03eSRichard abort();
8989a1d03eSRichard }
9089a1d03eSRichard
handler_signal(int)9189a1d03eSRichard void handler_signal(int) {
9289a1d03eSRichard // FIXME: It is only OK to call signal with the current signal number.
9389a1d03eSRichard signal(0, SIG_DFL);
9489a1d03eSRichard }
9589a1d03eSRichard
handler_false_condition(int)9689a1d03eSRichard void handler_false_condition(int) {
9789a1d03eSRichard if (0)
9889a1d03eSRichard printf("1234");
9989a1d03eSRichard // 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]
10089a1d03eSRichard // CHECK-NOTES: :[[@LINE+4]]:18: note: function 'handler_false_condition' registered here as signal handler
10189a1d03eSRichard }
10289a1d03eSRichard
test_false_condition(void)10389a1d03eSRichard void test_false_condition(void) {
10489a1d03eSRichard signal(SIGINT, handler_false_condition);
10589a1d03eSRichard }
10689a1d03eSRichard
handler_multiple_calls(int)10789a1d03eSRichard void handler_multiple_calls(int) {
10889a1d03eSRichard f_extern();
10989a1d03eSRichard // 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*6e75ec5eSBalázs Kéri // CHECK-NOTES: :[[@LINE+9]]:18: note: function 'handler_multiple_calls' registered here as signal handler
11189a1d03eSRichard printf("1234");
11289a1d03eSRichard // 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]
11389a1d03eSRichard // CHECK-NOTES: :[[@LINE+6]]:18: note: function 'handler_multiple_calls' registered here as signal handler
11489a1d03eSRichard f_extern();
11589a1d03eSRichard // first 'f_extern' call found only
11689a1d03eSRichard }
11789a1d03eSRichard
test_multiple_calls(void)11889a1d03eSRichard void test_multiple_calls(void) {
11989a1d03eSRichard signal(SIGINT, handler_multiple_calls);
12089a1d03eSRichard }
12189a1d03eSRichard
12289a1d03eSRichard void f_recursive(void);
12389a1d03eSRichard
handler_recursive(int)12489a1d03eSRichard void handler_recursive(int) {
12589a1d03eSRichard f_recursive();
12689a1d03eSRichard printf("");
12789a1d03eSRichard // first 'printf' call (in f_recursive) found only
12889a1d03eSRichard }
12989a1d03eSRichard
f_recursive(void)13089a1d03eSRichard void f_recursive(void) {
13189a1d03eSRichard f_extern();
13289a1d03eSRichard // 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*6e75ec5eSBalázs Kéri // CHECK-NOTES: :[[@LINE-8]]:3: note: function 'f_recursive' called here from 'handler_recursive'
134*6e75ec5eSBalázs Kéri // CHECK-NOTES: :[[@LINE+9]]:18: note: function 'handler_recursive' registered here as signal handler
13589a1d03eSRichard printf("");
13689a1d03eSRichard // 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*6e75ec5eSBalázs Kéri // CHECK-NOTES: :[[@LINE-12]]:3: note: function 'f_recursive' called here from 'handler_recursive'
13889a1d03eSRichard // CHECK-NOTES: :[[@LINE+5]]:18: note: function 'handler_recursive' registered here as signal handler
13989a1d03eSRichard handler_recursive(2);
14089a1d03eSRichard }
14189a1d03eSRichard
test_recursive(void)14289a1d03eSRichard void test_recursive(void) {
14389a1d03eSRichard signal(SIGINT, handler_recursive);
14489a1d03eSRichard }
14589a1d03eSRichard
f_multiple_paths(void)14689a1d03eSRichard void f_multiple_paths(void) {
14789a1d03eSRichard printf("");
14889a1d03eSRichard // 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]
14989a1d03eSRichard // CHECK-NOTES: :[[@LINE+5]]:3: note: function 'f_multiple_paths' called here from 'handler_multiple_paths'
15089a1d03eSRichard // CHECK-NOTES: :[[@LINE+9]]:18: note: function 'handler_multiple_paths' registered here as signal handler
15189a1d03eSRichard }
15289a1d03eSRichard
handler_multiple_paths(int)15389a1d03eSRichard void handler_multiple_paths(int) {
15489a1d03eSRichard f_multiple_paths();
15589a1d03eSRichard f_multiple_paths();
15689a1d03eSRichard }
15789a1d03eSRichard
test_multiple_paths(void)15889a1d03eSRichard void test_multiple_paths(void) {
15989a1d03eSRichard signal(SIGINT, handler_multiple_paths);
16089a1d03eSRichard }
16189a1d03eSRichard
handler_function_pointer(int)16289a1d03eSRichard void handler_function_pointer(int) {
16389a1d03eSRichard void (*fp)(void) = f_extern;
16489a1d03eSRichard // Call with function pointer is not evalauted by the check.
16589a1d03eSRichard (*fp)();
16689a1d03eSRichard }
16789a1d03eSRichard
test_function_pointer(void)16889a1d03eSRichard void test_function_pointer(void) {
16989a1d03eSRichard signal(SIGINT, handler_function_pointer);
17089a1d03eSRichard }
17189a1d03eSRichard
test_other(void)17289a1d03eSRichard void test_other(void) {
17389a1d03eSRichard signal(SIGINT, handler_abort);
17489a1d03eSRichard signal(SIGINT, handler_signal);
17589a1d03eSRichard
17689a1d03eSRichard signal(SIGINT, _Exit);
17789a1d03eSRichard signal(SIGINT, other_call);
17889a1d03eSRichard // 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]
179af01f717SAaron Ballman signal(SIGINT, f_extern_handler);
180af01f717SAaron Ballman // 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]
18189a1d03eSRichard
18289a1d03eSRichard signal(SIGINT, SIG_IGN);
18389a1d03eSRichard signal(SIGINT, SIG_DFL);
18489a1d03eSRichard }
185