Commit 4804c5fe by 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.
parent a6b5f19c
2020-01-14 David Malcolm <dmalcolm@redhat.com> 2020-01-14 David Malcolm <dmalcolm@redhat.com>
* analyzer-selftests.cc (selftest::run_analyzer_selftests): Call * 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. selftest::analyzer_function_set_cc_tests.
* analyzer-selftests.h (selftest::analyzer_function_set_cc_tests): * analyzer-selftests.h (selftest::analyzer_function_set_cc_tests):
New decl. New decl.
......
...@@ -54,6 +54,7 @@ run_analyzer_selftests () ...@@ -54,6 +54,7 @@ run_analyzer_selftests ()
analyzer_program_point_cc_tests (); analyzer_program_point_cc_tests ();
analyzer_program_state_cc_tests (); analyzer_program_state_cc_tests ();
analyzer_region_model_cc_tests (); analyzer_region_model_cc_tests ();
analyzer_sm_signal_cc_tests ();
#endif /* #if ENABLE_ANALYZER */ #endif /* #if ENABLE_ANALYZER */
} }
......
...@@ -37,6 +37,7 @@ extern void analyzer_function_set_cc_tests (); ...@@ -37,6 +37,7 @@ extern void analyzer_function_set_cc_tests ();
extern void analyzer_program_point_cc_tests (); extern void analyzer_program_point_cc_tests ();
extern void analyzer_program_state_cc_tests (); extern void analyzer_program_state_cc_tests ();
extern void analyzer_region_model_cc_tests (); extern void analyzer_region_model_cc_tests ();
extern void analyzer_sm_signal_cc_tests ();
} /* end of namespace selftest. */ } /* end of namespace selftest. */
......
...@@ -56,6 +56,8 @@ along with GCC; see the file COPYING3. If not see ...@@ -56,6 +56,8 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/diagnostic-manager.h" #include "analyzer/diagnostic-manager.h"
#include "shortest-paths.h" #include "shortest-paths.h"
#include "analyzer/exploded-graph.h" #include "analyzer/exploded-graph.h"
#include "analyzer/function-set.h"
#include "analyzer/analyzer-selftests.h"
#if ENABLE_ANALYZER #if ENABLE_ANALYZER
...@@ -246,16 +248,40 @@ public: ...@@ -246,16 +248,40 @@ public:
tree m_fndecl; 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 static function_set
signal_unsafe_p (tree callee_fndecl) get_async_signal_unsafe_fns ()
{ {
// TODO: maintain a list of known unsafe functions // TODO: populate this list more fully
if (is_named_call_p (callee_fndecl, "fprintf")) static const char * const async_signal_unsafe_fns[] = {
return true; /* 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. */ /* Implementation of state_machine::on_stmt vfunc for signal_state_machine. */
...@@ -325,4 +351,21 @@ make_signal_state_machine (logger *logger) ...@@ -325,4 +351,21 @@ make_signal_state_machine (logger *logger)
return new signal_state_machine (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 */ #endif /* #if ENABLE_ANALYZER */
2020-01-14 David Malcolm <dmalcolm@redhat.com> 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-1.c: Remove xfail.
* gcc.dg/analyzer/data-model-5b.c: Likewise. * gcc.dg/analyzer/data-model-5b.c: Likewise.
* gcc.dg/analyzer/data-model-5c.c: Likewise. * gcc.dg/analyzer/data-model-5c.c: Likewise.
......
/* 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment