analyzer: fix global-sm-state issue affecting sm-signal
sm-signal.cc was failing to warn about the use of an fprintf call in a signal handler when the signal handler function was non-static. The root cause was a failure to copy global sm-state within sm_state_map::clone_with_remapping as called by program_state::can_merge_with_p, which led to the exploded node for the entrypoint to the handler in the "normal" state being erroneously reused for the "in_signal_handler" state, thus losing the global state, and thus failing to warn. This patch fixes the above, so that non-equal global sm-state values prevent merger of program_state, thus requiring separate exploded nodes for the "normal" and "in signal handler" states, and thus triggering the warning for the reproducer. gcc/analyzer/ChangeLog: * program-state.cc (sm_state_map::clone_with_remapping): Copy m_global_state. (selftest::test_program_state_merging_2): New selftest. (selftest::analyzer_program_state_cc_tests): Call it. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/signal-6.c: New test.
This commit is contained in:
parent
e2a538b1c3
commit
7fb3669edb
@ -1,3 +1,10 @@
|
||||
2020-01-14 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* program-state.cc (sm_state_map::clone_with_remapping): Copy
|
||||
m_global_state.
|
||||
(selftest::test_program_state_merging_2): New selftest.
|
||||
(selftest::analyzer_program_state_cc_tests): Call it.
|
||||
|
||||
2020-01-14 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* checker-path.h (checker_path::get_checker_event): New function.
|
||||
|
@ -84,6 +84,7 @@ sm_state_map *
|
||||
sm_state_map::clone_with_remapping (const one_way_svalue_id_map &id_map) const
|
||||
{
|
||||
sm_state_map *result = new sm_state_map ();
|
||||
result->m_global_state = m_global_state;
|
||||
for (typename map_t::iterator iter = m_map.begin ();
|
||||
iter != m_map.end ();
|
||||
++iter)
|
||||
@ -1348,6 +1349,39 @@ test_program_state_merging ()
|
||||
ASSERT_EQ (s0, merged);
|
||||
}
|
||||
|
||||
/* Verify that program_states with different global-state in an sm-state
|
||||
can't be merged. */
|
||||
|
||||
static void
|
||||
test_program_state_merging_2 ()
|
||||
{
|
||||
auto_delete_vec <state_machine> checkers;
|
||||
checkers.safe_push (make_signal_state_machine (NULL));
|
||||
extrinsic_state ext_state (checkers);
|
||||
|
||||
program_state s0 (ext_state);
|
||||
{
|
||||
sm_state_map *smap0 = s0.m_checker_states[0];
|
||||
const state_machine::state_t TEST_STATE_0 = 0;
|
||||
smap0->set_global_state (TEST_STATE_0);
|
||||
ASSERT_EQ (smap0->get_global_state (), TEST_STATE_0);
|
||||
}
|
||||
|
||||
program_state s1 (ext_state);
|
||||
{
|
||||
sm_state_map *smap1 = s1.m_checker_states[0];
|
||||
const state_machine::state_t TEST_STATE_1 = 1;
|
||||
smap1->set_global_state (TEST_STATE_1);
|
||||
ASSERT_EQ (smap1->get_global_state (), TEST_STATE_1);
|
||||
}
|
||||
|
||||
ASSERT_NE (s0, s1);
|
||||
|
||||
/* They ought to not be mergeable. */
|
||||
program_state merged (ext_state);
|
||||
ASSERT_FALSE (s0.can_merge_with_p (s1, ext_state, &merged));
|
||||
}
|
||||
|
||||
/* Run all of the selftests within this file. */
|
||||
|
||||
void
|
||||
@ -1355,6 +1389,7 @@ analyzer_program_state_cc_tests ()
|
||||
{
|
||||
test_sm_state_map ();
|
||||
test_program_state_merging ();
|
||||
test_program_state_merging_2 ();
|
||||
}
|
||||
|
||||
} // namespace selftest
|
||||
|
@ -1,3 +1,7 @@
|
||||
2020-01-14 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* gcc.dg/analyzer/signal-6.c: New test.
|
||||
|
||||
2020-01-14 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* gcc.dg/analyzer/dot-output.c: Add test coverage for a BB with
|
||||
|
20
gcc/testsuite/gcc.dg/analyzer/signal-6.c
Normal file
20
gcc/testsuite/gcc.dg/analyzer/signal-6.c
Normal file
@ -0,0 +1,20 @@
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
extern void body_of_program(void);
|
||||
|
||||
/* Example of a non-static signal handler. */
|
||||
|
||||
void handler(int signum)
|
||||
{
|
||||
fprintf(stderr, "LOG: %i", signum); /* { dg-warning "call to 'fprintf' 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user