[gcc/devel/c++-modules] analyzer: introduce a set of known async-signal-unsafe functions

Nathan Sidwell nathan@gcc.gnu.org
Fri Jan 17 19:14:00 GMT 2020


https://gcc.gnu.org/g:4804c5fe965eef2f346de53d9e896ea2cd88f0b9

commit 4804c5fe965eef2f346de53d9e896ea2cd88f0b9
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Thu Dec 19 15:50:29 2019 -0500

    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.

Diff:
---
 gcc/analyzer/ChangeLog                   | 12 +++++++
 gcc/analyzer/analyzer-selftests.cc       |  1 +
 gcc/analyzer/analyzer-selftests.h        |  1 +
 gcc/analyzer/sm-signal.cc                | 57 ++++++++++++++++++++++++++++----
 gcc/testsuite/ChangeLog                  |  4 +++
 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;
+}



More information about the Gcc-cvs mailing list