GCC with patches for OS216
修訂 | 4804c5fe965eef2f346de53d9e896ea2cd88f0b9 (tree) |
---|---|
時間 | 2020-01-15 08:55:00 |
作者 | David Malcolm <dmalcolm@redh...> |
Commiter | David Malcolm |
analyzer: introduce a set of known async-signal-unsafe functions
This patch uses the class function_set from the previous patch to
generalize the test for an fprintf inside a signal handler to
check for a set of known async-signal-unsafe functions.
gcc/analyzer/ChangeLog:
* analyzer-selftests.cc (selftest::run_analyzer_selftests): Call
selftest::analyzer_sm_signal_cc_tests.
* analyzer-selftests.h (selftest::analyzer_sm_signal_cc_tests):
New decl.
* sm-signal.cc: Include "analyzer/function-set.h" and
"analyzer/analyzer-selftests.h".
(get_async_signal_unsafe_fns): New function.
(signal_unsafe_p): Reimplement in terms of the above.
(selftest::analyzer_sm_signal_cc_tests): New function.
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/signal-5.c: New test.
@@ -1,6 +1,18 @@ | ||
1 | 1 | 2020-01-14 David Malcolm <dmalcolm@redhat.com> |
2 | 2 | |
3 | 3 | * analyzer-selftests.cc (selftest::run_analyzer_selftests): Call |
4 | + selftest::analyzer_sm_signal_cc_tests. | |
5 | + * analyzer-selftests.h (selftest::analyzer_sm_signal_cc_tests): | |
6 | + New decl. | |
7 | + * sm-signal.cc: Include "analyzer/function-set.h" and | |
8 | + "analyzer/analyzer-selftests.h". | |
9 | + (get_async_signal_unsafe_fns): New function. | |
10 | + (signal_unsafe_p): Reimplement in terms of the above. | |
11 | + (selftest::analyzer_sm_signal_cc_tests): New function. | |
12 | + | |
13 | +2020-01-14 David Malcolm <dmalcolm@redhat.com> | |
14 | + | |
15 | + * analyzer-selftests.cc (selftest::run_analyzer_selftests): Call | |
4 | 16 | selftest::analyzer_function_set_cc_tests. |
5 | 17 | * analyzer-selftests.h (selftest::analyzer_function_set_cc_tests): |
6 | 18 | New decl. |
@@ -54,6 +54,7 @@ run_analyzer_selftests () | ||
54 | 54 | analyzer_program_point_cc_tests (); |
55 | 55 | analyzer_program_state_cc_tests (); |
56 | 56 | analyzer_region_model_cc_tests (); |
57 | + analyzer_sm_signal_cc_tests (); | |
57 | 58 | #endif /* #if ENABLE_ANALYZER */ |
58 | 59 | } |
59 | 60 |
@@ -37,6 +37,7 @@ extern void analyzer_function_set_cc_tests (); | ||
37 | 37 | extern void analyzer_program_point_cc_tests (); |
38 | 38 | extern void analyzer_program_state_cc_tests (); |
39 | 39 | extern void analyzer_region_model_cc_tests (); |
40 | +extern void analyzer_sm_signal_cc_tests (); | |
40 | 41 | |
41 | 42 | } /* end of namespace selftest. */ |
42 | 43 |
@@ -56,6 +56,8 @@ along with GCC; see the file COPYING3. If not see | ||
56 | 56 | #include "analyzer/diagnostic-manager.h" |
57 | 57 | #include "shortest-paths.h" |
58 | 58 | #include "analyzer/exploded-graph.h" |
59 | +#include "analyzer/function-set.h" | |
60 | +#include "analyzer/analyzer-selftests.h" | |
59 | 61 | |
60 | 62 | #if ENABLE_ANALYZER |
61 | 63 |
@@ -246,16 +248,40 @@ public: | ||
246 | 248 | tree m_fndecl; |
247 | 249 | }; |
248 | 250 | |
249 | -/* Return true if CALL is known to be unsafe to call from a signal handler. */ | |
251 | +/* Get a set of functions that are known to be unsafe to call from an | |
252 | + async signal handler. */ | |
250 | 253 | |
251 | -static bool | |
252 | -signal_unsafe_p (tree callee_fndecl) | |
254 | +static function_set | |
255 | +get_async_signal_unsafe_fns () | |
253 | 256 | { |
254 | - // TODO: maintain a list of known unsafe functions | |
255 | - if (is_named_call_p (callee_fndecl, "fprintf")) | |
256 | - return true; | |
257 | + // TODO: populate this list more fully | |
258 | + static const char * const async_signal_unsafe_fns[] = { | |
259 | + /* This array must be kept sorted. */ | |
260 | + "fprintf", | |
261 | + "free", | |
262 | + "malloc", | |
263 | + "printf", | |
264 | + "snprintf", | |
265 | + "sprintf", | |
266 | + "vfprintf", | |
267 | + "vprintf", | |
268 | + "vsnprintf", | |
269 | + "vsprintf" | |
270 | + }; | |
271 | + const size_t count | |
272 | + = sizeof(async_signal_unsafe_fns) / sizeof (async_signal_unsafe_fns[0]); | |
273 | + function_set fs (async_signal_unsafe_fns, count); | |
274 | + return fs; | |
275 | +}; | |
257 | 276 | |
258 | - return false; | |
277 | +/* Return true if FNDECL is known to be unsafe to call from a signal | |
278 | + handler. */ | |
279 | + | |
280 | +static bool | |
281 | +signal_unsafe_p (tree fndecl) | |
282 | +{ | |
283 | + function_set fs = get_async_signal_unsafe_fns (); | |
284 | + return fs.contains_decl_p (fndecl); | |
259 | 285 | } |
260 | 286 | |
261 | 287 | /* Implementation of state_machine::on_stmt vfunc for signal_state_machine. */ |
@@ -325,4 +351,21 @@ make_signal_state_machine (logger *logger) | ||
325 | 351 | return new signal_state_machine (logger); |
326 | 352 | } |
327 | 353 | |
354 | +#if CHECKING_P | |
355 | + | |
356 | +namespace selftest { | |
357 | + | |
358 | +/* Run all of the selftests within this file. */ | |
359 | + | |
360 | +void | |
361 | +analyzer_sm_signal_cc_tests () | |
362 | +{ | |
363 | + function_set fs = get_async_signal_unsafe_fns (); | |
364 | + fs.assert_sorted (); | |
365 | + fs.assert_sane (); | |
366 | +} | |
367 | + | |
368 | +} // namespace selftest | |
369 | + | |
370 | +#endif /* CHECKING_P */ | |
328 | 371 | #endif /* #if ENABLE_ANALYZER */ |
@@ -1,5 +1,9 @@ | ||
1 | 1 | 2020-01-14 David Malcolm <dmalcolm@redhat.com> |
2 | 2 | |
3 | + * gcc.dg/analyzer/signal-5.c: New test. | |
4 | + | |
5 | +2020-01-14 David Malcolm <dmalcolm@redhat.com> | |
6 | + | |
3 | 7 | * gcc.dg/analyzer/data-model-1.c: Remove xfail. |
4 | 8 | * gcc.dg/analyzer/data-model-5b.c: Likewise. |
5 | 9 | * gcc.dg/analyzer/data-model-5c.c: Likewise. |
@@ -0,0 +1,21 @@ | ||
1 | +/* Example of other bad calls within a signal handler. */ | |
2 | + | |
3 | +#include <stdlib.h> | |
4 | +#include <signal.h> | |
5 | + | |
6 | +extern void do_stuff (void *ptr); | |
7 | +extern void body_of_program(void); | |
8 | + | |
9 | +static void handler(int signum) | |
10 | +{ | |
11 | + void *ptr = malloc (1024); /* { dg-warning "call to 'malloc' from within signal handler" } */ | |
12 | + do_stuff (ptr); | |
13 | + free (ptr); /* { dg-warning "call to 'free' from within signal handler" } */ | |
14 | +} | |
15 | + | |
16 | +int main(int argc, const char *argv) | |
17 | +{ | |
18 | + signal(SIGINT, handler); /* { dg-message "registering 'handler' as signal handler" } */ | |
19 | + body_of_program(); | |
20 | + return 0; | |
21 | +} |