aboutsummaryrefslogtreecommitdiff
path: root/gcc/analyzer/svalue.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/svalue.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/svalue.cc')
-rw-r--r--gcc/analyzer/svalue.cc34
1 files changed, 34 insertions, 0 deletions
diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc
index d6305a3..897e84e 100644
--- a/gcc/analyzer/svalue.cc
+++ b/gcc/analyzer/svalue.cc
@@ -481,6 +481,40 @@ svalue::cmp_ptr_ptr (const void *p1, const void *p2)
return cmp_ptr (sval1, sval2);
}
+/* Subclass of visitor for use in implementing svalue::involves_p. */
+
+class involvement_visitor : public visitor
+{
+public:
+ involvement_visitor (const svalue *needle)
+ : m_needle (needle), m_found (false) {}
+
+ void visit_initial_svalue (const initial_svalue *candidate)
+ {
+ if (candidate == m_needle)
+ m_found = true;
+ }
+
+ bool found_p () const { return m_found; }
+
+private:
+ const svalue *m_needle;
+ bool m_found;
+};
+
+/* Return true iff this svalue is defined in terms of OTHER. */
+
+bool
+svalue::involves_p (const svalue *other) const
+{
+ /* Currently only implemented for initial_svalue. */
+ gcc_assert (other->get_kind () == SK_INITIAL);
+
+ involvement_visitor v (other);
+ accept (&v);
+ return v.found_p ();
+}
+
/* class region_svalue : public svalue. */
/* Implementation of svalue::dump_to_pp vfunc for region_svalue. */