aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/sm-signal.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2019-12-19 15:50:29 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2020-01-14 18:55:00 -0500
commit4804c5fe965eef2f346de53d9e896ea2cd88f0b9 (patch)
tree76c4abc5bfcbe0daa782d729afabba990b77dc42 /gcc/analyzer/sm-signal.cc
parenta6b5f19c37001d7c9974248ffcb65aadba33283c (diff)
downloadgcc-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.
Diffstat (limited to 'gcc/analyzer/sm-signal.cc')
-rw-r--r--gcc/analyzer/sm-signal.cc57
1 files changed, 50 insertions, 7 deletions
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 */