public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/c++-modules] analyzer: fix ICE due to missing state_change purging (PR 93374)
@ 2020-02-24 16:16 Nathan Sidwell
  0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2020-02-24 16:16 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:a60d98890bba58649c26c2fc0c6f28cd6073aaaf

commit a60d98890bba58649c26c2fc0c6f28cd6073aaaf
Author: David Malcolm <dmalcolm@redhat.com>
Date:   Tue Feb 11 10:52:40 2020 -0500

    analyzer: fix ICE due to missing state_change purging (PR 93374)
    
    PR analyzer/93374 reports an ICE within state_change::validate due to an
    m_new_sid in a recorded state-change being out of range of the svalues
    of the region_model of the new state.
    
    During get_or_create_node we attempt to merge the new state with the
    state of each of the existing enodes at the program point (in the
    absence of sm-state differences), simplifying the state at each
    attempt, and potentially reusing a node if we get a match.
    
    This state-merging invalidates any svalue_ids within any state_change
    object.
    
    The root cause is that, although the code was purging any such
    svalue_ids for the case where no match was found during merging, it was
    failing to purge them for the case where a matching enode *was* found
    for the merged state, leading to an invalid state_change along the
    exploded_edge to the reused enode.
    
    This patch moves the invalidation code to cover both cases, fixing the
    ICE.  It also extends state_change validation so that states are also
    checked.
    
    gcc/analyzer/ChangeLog:
    	PR analyzer/93374
    	* engine.cc (exploded_edge::exploded_edge): Add ext_state param
    	and pass it to change.validate.
    	(exploded_graph::get_or_create_node): Move purging of change
    	svalues to also cover the case of reusing an existing enode.
    	(exploded_graph::add_edge): Pass m_ext_state to exploded_edge's
    	ctor.
    	* exploded-graph.h (exploded_edge::exploded_edge): Add ext_state
    	param.
    	* program-state.cc (state_change::sm_change::validate): Likewise.
    	Assert that m_sm_idx is sane.  Use ext_state to validate
    	m_old_state and m_new_state.
    	(state_change::validate): Add ext_state param and pass it to
    	the sm_change validate calls.
    	* program-state.h (state_change::sm_change::validate): Add
    	ext_state param.
    	(state_change::validate): Likewise.
    
    gcc/testsuite/ChangeLog:
    	PR analyzer/93374
    	* gcc.dg/analyzer/torture/pr93374.c: New test.

Diff:
---
 gcc/analyzer/ChangeLog                          | 20 ++++++++++++++++++++
 gcc/analyzer/engine.cc                          | 21 +++++++++++----------
 gcc/analyzer/exploded-graph.h                   |  1 +
 gcc/analyzer/program-state.cc                   | 12 +++++++++---
 gcc/analyzer/program-state.h                    |  6 ++++--
 gcc/testsuite/ChangeLog                         |  5 +++++
 gcc/testsuite/gcc.dg/analyzer/torture/pr93374.c |  2 ++
 7 files changed, 52 insertions(+), 15 deletions(-)

diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index 0734716..0313e43 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,5 +1,25 @@
 2020-02-11  David Malcolm  <dmalcolm@redhat.com>
 
+	PR analyzer/93374
+	* engine.cc (exploded_edge::exploded_edge): Add ext_state param
+	and pass it to change.validate.
+	(exploded_graph::get_or_create_node): Move purging of change
+	svalues to also cover the case of reusing an existing enode.
+	(exploded_graph::add_edge): Pass m_ext_state to exploded_edge's
+	ctor.
+	* exploded-graph.h (exploded_edge::exploded_edge): Add ext_state
+	param.
+	* program-state.cc (state_change::sm_change::validate): Likewise.
+	Assert that m_sm_idx is sane.  Use ext_state to validate
+	m_old_state and m_new_state.
+	(state_change::validate): Add ext_state param and pass it to
+	the sm_change validate calls.
+	* program-state.h (state_change::sm_change::validate): Add
+	ext_state param.
+	(state_change::validate): Likewise.
+
+2020-02-11  David Malcolm  <dmalcolm@redhat.com>
+
 	PR analyzer/93669
 	* engine.cc (exploded_graph::dump_exploded_nodes): Handle missing
 	case of STATUS_WORKLIST in implementation of
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 8d5f9c6..4d329e2 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -1398,13 +1398,14 @@ rewind_info_t::add_events_to_path (checker_path *emission_path,
 /* exploded_edge's ctor.  */
 
 exploded_edge::exploded_edge (exploded_node *src, exploded_node *dest,
+			      const extrinsic_state &ext_state,
 			      const superedge *sedge,
 			      const state_change &change,
 			      custom_info_t *custom_info)
 : dedge<eg_traits> (src, dest), m_sedge (sedge), m_change (change),
   m_custom_info (custom_info)
 {
-  change.validate (dest->get_state ());
+  change.validate (dest->get_state (), ext_state);
 }
 
 /* exploded_edge's dtor.  */
@@ -1898,8 +1899,14 @@ exploded_graph::get_or_create_node (const program_point &point,
 		logger->log ("merging new state with that of EN: %i",
 			     existing_enode->m_index);
 
-	      /* Try again for a cache hit.  */
+	      /* Try again for a cache hit.
+		 Whether we get one or not, merged_state's value_ids have no
+		 relationship to those of the input state, and thus to those
+		 of CHANGE, so we must purge any svalue_ids from *CHANGE.  */
 	      ps.set_state (merged_state);
+	      if (change)
+		change->on_svalue_purge (svalue_id::from_int (0));
+
 	      if (exploded_node **slot = m_point_and_state_to_node.get (&ps))
 		{
 		  /* An exploded_node for PS already exists.  */
@@ -1910,13 +1917,6 @@ exploded_graph::get_or_create_node (const program_point &point,
 		  per_cs_stats->m_node_reuse_after_merge_count++;
 		  return *slot;
 		}
-
-	      /* Otherwise, continue, using the merged state in "ps".
-		 Given that merged_state's svalue_ids have no relationship
-		 to those of the input state, and thus to those of CHANGE,
-		 purge any svalue_ids from *CHANGE.  */
-	      if (change)
-		change->on_svalue_purge (svalue_id::from_int (0));
 	    }
 	  else
 	    if (logger)
@@ -1986,7 +1986,8 @@ exploded_graph::add_edge (exploded_node *src, exploded_node *dest,
 			  const state_change &change,
 			  exploded_edge::custom_info_t *custom_info)
 {
-  exploded_edge *e = new exploded_edge (src, dest, sedge, change, custom_info);
+  exploded_edge *e = new exploded_edge (src, dest, m_ext_state,
+					sedge, change, custom_info);
   digraph<eg_traits>::add_edge (e);
   return e;
 }
diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h
index e47816a..5d69bff 100644
--- a/gcc/analyzer/exploded-graph.h
+++ b/gcc/analyzer/exploded-graph.h
@@ -306,6 +306,7 @@ class exploded_edge : public dedge<eg_traits>
   };
 
   exploded_edge (exploded_node *src, exploded_node *dest,
+		 const extrinsic_state &ext_state,
 		 const superedge *sedge,
 		 const state_change &change,
 		 custom_info_t *custom_info);
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 4c0b9a8..82b921e 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -1083,8 +1083,13 @@ state_change::sm_change::on_svalue_purge (svalue_id first_unused_sid)
 /* Assert that this object is sane.  */
 
 void
-state_change::sm_change::validate (const program_state &new_state) const
+state_change::sm_change::validate (const program_state &new_state,
+				   const extrinsic_state &ext_state) const
 {
+  gcc_assert ((unsigned)m_sm_idx < ext_state.get_num_checkers ());
+  const state_machine &sm = ext_state.get_sm (m_sm_idx);
+  sm.validate (m_old_state);
+  sm.validate (m_new_state);
   m_new_sid.validate (*new_state.m_region_model);
 }
 
@@ -1191,7 +1196,8 @@ state_change::on_svalue_purge (svalue_id first_unused_sid)
 /* Assert that this object is sane.  */
 
 void
-state_change::validate (const program_state &new_state) const
+state_change::validate (const program_state &new_state,
+			const extrinsic_state &ext_state) const
 {
   /* Skip this in a release build.  */
 #if !CHECKING_P
@@ -1200,7 +1206,7 @@ state_change::validate (const program_state &new_state) const
   unsigned i;
   sm_change *change;
   FOR_EACH_VEC_ELT (m_sm_changes, i, change)
-    change->validate (new_state);
+    change->validate (new_state, ext_state);
 }
 
 #if CHECKING_P
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index d2badb1..a4608c7 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -343,7 +343,8 @@ class state_change
     void remap_svalue_ids (const svalue_id_map &map);
     int on_svalue_purge (svalue_id first_unused_sid);
 
-    void validate (const program_state &new_state) const;
+    void validate (const program_state &new_state,
+		   const extrinsic_state &ext_state) const;
 
     int m_sm_idx;
     svalue_id m_new_sid;
@@ -367,7 +368,8 @@ class state_change
   void remap_svalue_ids (const svalue_id_map &map);
   int on_svalue_purge (svalue_id first_unused_sid);
 
-  void validate (const program_state &new_state) const;
+  void validate (const program_state &new_state,
+		 const extrinsic_state &ext_state) const;
 
  private:
   auto_vec<sm_change> m_sm_changes;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index f75a678..4f59153 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
 2020-02-11  David Malcolm  <dmalcolm@redhat.com>
 
+	PR analyzer/93374
+	* gcc.dg/analyzer/torture/pr93374.c: New test.
+
+2020-02-11  David Malcolm  <dmalcolm@redhat.com>
+
 	PR analyzer/93669
 	* gcc.dg/analyzer/pr93669.c: New test.
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/pr93374.c b/gcc/testsuite/gcc.dg/analyzer/torture/pr93374.c
new file mode 100644
index 0000000..a7adecd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/torture/pr93374.c
@@ -0,0 +1,2 @@
+#include <stdlib.h>
+#include "../../../gcc.c-torture/execute/pr27073.c"


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-02-24 16:16 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-24 16:16 [gcc/devel/c++-modules] analyzer: fix ICE due to missing state_change purging (PR 93374) Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).