diff options
author | David Malcolm <dmalcolm@redhat.com> | 2021-03-24 20:47:57 -0400 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2021-03-24 20:47:57 -0400 |
commit | 71fc4655ab86ab66b40165b2cb49c1395ca82a9a (patch) | |
tree | cd0439f92df03d57f9d79983cdd9b76ead8f09fc /gcc/analyzer/program-state.cc | |
parent | 8bf52ffa92f7d1539cbb82fbc0e95389e084ec31 (diff) | |
download | gcc-71fc4655ab86ab66b40165b2cb49c1395ca82a9a.zip gcc-71fc4655ab86ab66b40165b2cb49c1395ca82a9a.tar.gz gcc-71fc4655ab86ab66b40165b2cb49c1395ca82a9a.tar.bz2 |
analyzer; reset sm-state for SSA names at def-stmts [PR93695,PR99044,PR99716]
Various false positives from -fanalyzer involve SSA names in loops,
where sm-state associated with an SSA name from one iteration is
erroneously reused in a subsequent iteration.
For example, PR analyzer/99716 describes a false
"double 'fclose' of FILE 'fp'"
on:
for (i = 0; i < 2; ++i) {
FILE *fp = fopen ("/tmp/test", "w");
fprintf (fp, "hello");
fclose (fp);
}
where the gimple of the loop body is:
fp_7 = fopen ("/tmp/test", "w");
__builtin_fwrite ("hello", 1, 5, fp_7);
fclose (fp_7);
i_10 = i_1 + 1;
where fp_7 transitions to "closed" at the fclose, but is not
reset at the subsequent fopen, leading to the false positive
when the fclose is re-reached.
The fix is to reset sm-state for svalues that involve an SSA name
at the SSA name's def-stmt, since the def-stmt effectively changes
the meaning of those related svalues.
gcc/analyzer/ChangeLog:
PR analyzer/93695
PR analyzer/99044
PR analyzer/99716
* engine.cc (exploded_node::on_stmt): Clear sm-state involving
an SSA name at the def-stmt of that SSA name.
* program-state.cc (sm_state_map::purge_state_involving): New.
* program-state.h (sm_state_map::purge_state_involving): New decl.
* region-model.cc (selftest::test_involves_p): New.
(selftest::analyzer_region_model_cc_tests): Call it.
* svalue.cc (class involvement_visitor): New class
(svalue::involves_p): New.
* svalue.h (svalue::involves_p): New decl.
gcc/testsuite/ChangeLog:
PR analyzer/93695
PR analyzer/99044
PR analyzer/99716
* gcc.dg/analyzer/attr-malloc-CVE-2019-19078-usb-leak.c: Remove
xfail.
* gcc.dg/analyzer/pr93695-1.c: New test.
* gcc.dg/analyzer/pr99044-1.c: New test.
* gcc.dg/analyzer/pr99044-2.c: New test.
* gcc.dg/analyzer/pr99716-1.c: New test.
* gcc.dg/analyzer/pr99716-2.c: New test.
* gcc.dg/analyzer/pr99716-3.c: New test.
Diffstat (limited to 'gcc/analyzer/program-state.cc')
-rw-r--r-- | gcc/analyzer/program-state.cc | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index e427fff..fcea5ce 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -586,6 +586,36 @@ sm_state_map::on_unknown_change (const svalue *sval, impl_set_state (*iter, (state_machine::state_t)0, NULL, ext_state); } +/* Purge state for things involving SVAL. + For use when SVAL changes meaning, at the def_stmt on an SSA_NAME. */ + +void +sm_state_map::purge_state_involving (const svalue *sval, + const extrinsic_state &ext_state) +{ + /* Currently svalue::involves_p requires this. */ + if (sval->get_kind () != SK_INITIAL) + return; + + svalue_set svals_to_unset; + + for (map_t::iterator iter = m_map.begin (); + iter != m_map.end (); + ++iter) + { + const svalue *key = (*iter).first; + entry_t e = (*iter).second; + if (!m_sm.can_purge_p (e.m_state)) + continue; + if (key->involves_p (sval)) + svals_to_unset.add (key); + } + + for (svalue_set::iterator iter = svals_to_unset.begin (); + iter != svals_to_unset.end (); ++iter) + impl_set_state (*iter, (state_machine::state_t)0, NULL, ext_state); +} + /* Comparator for imposing an order on sm_state_map instances. */ int |