diff options
author | David Malcolm <dmalcolm@redhat.com> | 2019-12-19 15:50:29 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2020-01-14 18:55:00 -0500 |
commit | 4804c5fe965eef2f346de53d9e896ea2cd88f0b9 (patch) | |
tree | 76c4abc5bfcbe0daa782d729afabba990b77dc42 | |
parent | a6b5f19c37001d7c9974248ffcb65aadba33283c (diff) | |
download | gcc-4804c5fe965eef2f346de53d9e896ea2cd88f0b9.zip gcc-4804c5fe965eef2f346de53d9e896ea2cd88f0b9.tar.gz gcc-4804c5fe965eef2f346de53d9e896ea2cd88f0b9.tar.bz2 |
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.
-rw-r--r-- | gcc/analyzer/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/analyzer/analyzer-selftests.cc | 1 | ||||
-rw-r--r-- | gcc/analyzer/analyzer-selftests.h | 1 | ||||
-rw-r--r-- | gcc/analyzer/sm-signal.cc | 57 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/signal-5.c | 21 |
6 files changed, 89 insertions, 7 deletions
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index 93efb47..bb3ac72 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,6 +1,18 @@ 2020-01-14 David Malcolm <dmalcolm@redhat.com> * 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. + +2020-01-14 David Malcolm <dmalcolm@redhat.com> + + * analyzer-selftests.cc (selftest::run_analyzer_selftests): Call selftest::analyzer_function_set_cc_tests. * analyzer-selftests.h (selftest::analyzer_function_set_cc_tests): New decl. diff --git a/gcc/analyzer/analyzer-selftests.cc b/gcc/analyzer/analyzer-selftests.cc index 99b730a..2b8fa81 100644 --- a/gcc/analyzer/analyzer-selftests.cc +++ b/gcc/analyzer/analyzer-selftests.cc @@ -54,6 +54,7 @@ run_analyzer_selftests () analyzer_program_point_cc_tests (); analyzer_program_state_cc_tests (); analyzer_region_model_cc_tests (); + analyzer_sm_signal_cc_tests (); #endif /* #if ENABLE_ANALYZER */ } diff --git a/gcc/analyzer/analyzer-selftests.h b/gcc/analyzer/analyzer-selftests.h index 61e3a02..80be32f 100644 --- a/gcc/analyzer/analyzer-selftests.h +++ b/gcc/analyzer/analyzer-selftests.h @@ -37,6 +37,7 @@ extern void analyzer_function_set_cc_tests (); extern void analyzer_program_point_cc_tests (); extern void analyzer_program_state_cc_tests (); extern void analyzer_region_model_cc_tests (); +extern void analyzer_sm_signal_cc_tests (); } /* end of namespace selftest. */ diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc index ee41d19..0057ab9 100644 --- a/gcc/analyzer/sm-signal.cc +++ b/gcc/analyzer/sm-signal.cc @@ -56,6 +56,8 @@ along with GCC; see the file COPYING3. If not see #include "analyzer/diagnostic-manager.h" #include "shortest-paths.h" #include "analyzer/exploded-graph.h" +#include "analyzer/function-set.h" +#include "analyzer/analyzer-selftests.h" #if ENABLE_ANALYZER @@ -246,16 +248,40 @@ public: tree m_fndecl; }; -/* Return true if CALL is known to be unsafe to call from a signal handler. */ +/* Get a set of functions that are known to be unsafe to call from an + async signal handler. */ -static bool -signal_unsafe_p (tree callee_fndecl) +static function_set +get_async_signal_unsafe_fns () { - // TODO: maintain a list of known unsafe functions - if (is_named_call_p (callee_fndecl, "fprintf")) - return true; + // TODO: populate this list more fully + static const char * const async_signal_unsafe_fns[] = { + /* This array must be kept sorted. */ + "fprintf", + "free", + "malloc", + "printf", + "snprintf", + "sprintf", + "vfprintf", + "vprintf", + "vsnprintf", + "vsprintf" + }; + const size_t count + = sizeof(async_signal_unsafe_fns) / sizeof (async_signal_unsafe_fns[0]); + function_set fs (async_signal_unsafe_fns, count); + return fs; +}; - return false; +/* Return true if FNDECL is known to be unsafe to call from a signal + handler. */ + +static bool +signal_unsafe_p (tree fndecl) +{ + function_set fs = get_async_signal_unsafe_fns (); + return fs.contains_decl_p (fndecl); } /* Implementation of state_machine::on_stmt vfunc for signal_state_machine. */ @@ -325,4 +351,21 @@ make_signal_state_machine (logger *logger) return new signal_state_machine (logger); } +#if CHECKING_P + +namespace selftest { + +/* Run all of the selftests within this file. */ + +void +analyzer_sm_signal_cc_tests () +{ + function_set fs = get_async_signal_unsafe_fns (); + fs.assert_sorted (); + fs.assert_sane (); +} + +} // namespace selftest + +#endif /* CHECKING_P */ #endif /* #if ENABLE_ANALYZER */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index efff14c..8013bdb 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2020-01-14 David Malcolm <dmalcolm@redhat.com> + * gcc.dg/analyzer/signal-5.c: New test. + +2020-01-14 David Malcolm <dmalcolm@redhat.com> + * gcc.dg/analyzer/data-model-1.c: Remove xfail. * gcc.dg/analyzer/data-model-5b.c: Likewise. * gcc.dg/analyzer/data-model-5c.c: Likewise. diff --git a/gcc/testsuite/gcc.dg/analyzer/signal-5.c b/gcc/testsuite/gcc.dg/analyzer/signal-5.c new file mode 100644 index 0000000..4e464ff --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/signal-5.c @@ -0,0 +1,21 @@ +/* Example of other bad calls within a signal handler. */ + +#include <stdlib.h> +#include <signal.h> + +extern void do_stuff (void *ptr); +extern void body_of_program(void); + +static void handler(int signum) +{ + void *ptr = malloc (1024); /* { dg-warning "call to 'malloc' from within signal handler" } */ + do_stuff (ptr); + free (ptr); /* { dg-warning "call to 'free' from within signal handler" } */ +} + +int main(int argc, const char *argv) +{ + signal(SIGINT, handler); /* { dg-message "registering 'handler' as signal handler" } */ + body_of_program(); + return 0; +} |