diff options
author | Mark Wielaard <mark@klomp.org> | 2020-05-17 23:50:41 +0200 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2020-05-22 21:02:34 +0200 |
commit | 2221fb6f668a7edc8b8aad69772907aeabbbb0be (patch) | |
tree | c04cf71d53e1f9980c4b2cce159a2c752fd607ab /gcc | |
parent | dc50686d78d4679b727548c3edc1cb6b0d3b658e (diff) | |
download | gcc-2221fb6f668a7edc8b8aad69772907aeabbbb0be.zip gcc-2221fb6f668a7edc8b8aad69772907aeabbbb0be.tar.gz gcc-2221fb6f668a7edc8b8aad69772907aeabbbb0be.tar.bz2 |
analyzer: Add exit, and _exit replacement, to sm-signal.
Warn about using exit in signal handler and suggest _exit as alternative.
gcc/analyzer/ChangeLog:
* sm-signal.cc(signal_unsafe_call::emit): Possibly add
gcc_rich_location note for replacement.
(signal_unsafe_call::get_replacement_fn): New private function.
(get_async_signal_unsafe_fns): Add "exit".
gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/signal-exit.c: New testcase.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/analyzer/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/analyzer/sm-signal.cc | 42 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/analyzer/signal-exit.c | 23 |
4 files changed, 72 insertions, 4 deletions
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index 5cd7363..d2c440a 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,3 +1,10 @@ +2020-05-22 Mark Wielaard <mark@klomp.org> + + * sm-signal.cc(signal_unsafe_call::emit): Possibly add + gcc_rich_location note for replacement. + (signal_unsafe_call::get_replacement_fn): New private function. + (get_async_signal_unsafe_fns): Add "exit". + 2020-04-28 David Malcolm <dmalcolm@redhat.com> PR analyzer/94816 diff --git a/gcc/analyzer/sm-signal.cc b/gcc/analyzer/sm-signal.cc index 5935e22..c002032 100644 --- a/gcc/analyzer/sm-signal.cc +++ b/gcc/analyzer/sm-signal.cc @@ -123,13 +123,32 @@ public: bool emit (rich_location *rich_loc) FINAL OVERRIDE { + auto_diagnostic_group d; diagnostic_metadata m; /* CWE-479: Signal Handler Use of a Non-reentrant Function. */ m.add_cwe (479); - return warning_meta (rich_loc, m, - OPT_Wanalyzer_unsafe_call_within_signal_handler, - "call to %qD from within signal handler", - m_unsafe_fndecl); + if (warning_meta (rich_loc, m, + OPT_Wanalyzer_unsafe_call_within_signal_handler, + "call to %qD from within signal handler", + m_unsafe_fndecl)) + { + /* If we know a possible alternative function, add a note + suggesting the replacement. */ + if (const char *replacement = get_replacement_fn ()) + { + location_t note_loc = gimple_location (m_unsafe_call); + /* It would be nice to add a fixit, but the gimple call + location covers the whole call expression. It isn't + currently possible to cut this down to just the call + symbol. So the fixit would replace too much. + note_rich_loc.add_fixit_replace (replacement); */ + inform (note_loc, + "%qs is a possible signal-safe alternative for %qD", + replacement, m_unsafe_fndecl); + } + return true; + } + return false; } label_text describe_state_change (const evdesc::state_change &change) @@ -156,6 +175,20 @@ private: const signal_state_machine &m_sm; const gcall *m_unsafe_call; tree m_unsafe_fndecl; + + /* Returns a replacement function as text if it exists. Currently + only "exit" has a signal-safe replacement "_exit", which does + slightly less, but can be used in a signal handler. */ + const char * + get_replacement_fn () + { + gcc_assert (m_unsafe_fndecl && DECL_P (m_unsafe_fndecl)); + + if (id_equal ("exit", DECL_NAME (m_unsafe_fndecl))) + return "_exit"; + + return NULL; + } }; /* signal_state_machine's ctor. */ @@ -259,6 +292,7 @@ get_async_signal_unsafe_fns () // TODO: populate this list more fully static const char * const async_signal_unsafe_fns[] = { /* This array must be kept sorted. */ + "exit", "fprintf", "free", "malloc", diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1dbdc38..bedaf9a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2020-05-22 Mark Wielaard <mark@klomp.org> + + * gcc.dg/analyzer/signal-exit.c: New testcase. + 2020-05-22 Uroš Bizjak <ubizjak@gmail.com> PR target/95255 diff --git a/gcc/testsuite/gcc.dg/analyzer/signal-exit.c b/gcc/testsuite/gcc.dg/analyzer/signal-exit.c new file mode 100644 index 0000000..a567124 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/signal-exit.c @@ -0,0 +1,23 @@ +/* Example of a bad call within a signal handler with replacement + alternative. 'handler' calls 'exit', and 'exit' is not allowed + from a signal handler. But '_exit' is allowed. */ + +#include <signal.h> +#include <stdlib.h> + +extern void body_of_program(void); + +static void handler(int signum) +{ + exit(1); /* { dg-warning "call to 'exit' from within signal handler" "warning" } */ + /* { dg-message "note: '_exit' is a possible signal-safe alternative for 'exit'" "replacement note" { target *-*-* } .-1 } */ +} + +int main(int argc, const char *argv) +{ + signal(SIGINT, handler); /* { dg-message "registering 'handler' as signal handler" } */ + + body_of_program(); + + return 0; +} |