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.
This commit is contained in:
parent
dc50686d78
commit
2221fb6f66
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
23
gcc/testsuite/gcc.dg/analyzer/signal-exit.c
Normal file
23
gcc/testsuite/gcc.dg/analyzer/signal-exit.c
Normal file
@ -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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user