aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/program-state.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2021-03-24 20:47:57 -0400
committerDavid Malcolm <dmalcolm@redhat.com>2021-03-24 20:47:57 -0400
commit71fc4655ab86ab66b40165b2cb49c1395ca82a9a (patch)
treecd0439f92df03d57f9d79983cdd9b76ead8f09fc /gcc/analyzer/program-state.cc
parent8bf52ffa92f7d1539cbb82fbc0e95389e084ec31 (diff)
downloadgcc-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.cc30
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