From 4bdcd3b32535cafc58d35be01fed20f2e6b6c4ce Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 25 Mar 2019 14:35:26 -0400
Subject: [PATCH 140/161] FIXME: WIP on recording event IDs

---
 gcc/analyzer/engine.cc                         | 23 ++++++++++++-----
 gcc/analyzer/hardcoded-state-machine-malloc.cc | 35 ++++++++++++++++++++++----
 gcc/analyzer/hardcoded-state-machine.h         | 24 +++++++++++++++++-
 3 files changed, 70 insertions(+), 12 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index db751ab..b866ba2 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -541,7 +541,7 @@ public:
   checker_event (enum event_kind kind,
 		 location_t loc, tree fndecl, int depth)
     : m_kind (kind), m_loc (loc), m_fndecl (fndecl), m_depth (depth),
-      m_pending_diagnostic (NULL)
+      m_pending_diagnostic (NULL), m_emission_id ()
   {
   }
 
@@ -567,9 +567,10 @@ public:
     return result;
   }
 
-  void set_pending_diagnostic (pending_diagnostic *pd)
+  void prepare_for_emission (pending_diagnostic *pd, event_id_t emission_id)
   {
     m_pending_diagnostic = pd;
+    m_emission_id = emission_id;
   }
 
   enum event_kind m_kind;
@@ -577,6 +578,7 @@ public:
   tree m_fndecl;
   int m_depth;
   pending_diagnostic *m_pending_diagnostic;
+  event_id_t m_emission_id; // only set once all pruning has occurred
 };
 
 class debug_event : public checker_event
@@ -698,7 +700,7 @@ public:
 	    label_text custom_desc
 	      = m_pending_diagnostic->describe_critical_state_change
 	      (//diagnostic_context *ctxt,
-	       m_var, m_from, m_to);
+	       m_var, m_from, m_to, m_emission_id);
 	    if (custom_desc.m_buffer)
 	      return custom_desc;
 	  }
@@ -932,12 +934,21 @@ public:
 #endif
   }
 
-  void set_pending_diagnostic (pending_diagnostic *pd)
+  void prepare_for_emission (pending_diagnostic *pd)
   {
     checker_event *e;
     int i;
     FOR_EACH_VEC_ELT (m_events, i, e)
-      e->set_pending_diagnostic (pd);
+      e->prepare_for_emission (pd, event_id_t (i));
+  }
+
+  event_id_t get_final_event_id () const
+  {
+    unsigned num = num_events ();
+    if (num > 0)
+      return event_id_t (num - 1);
+    else
+      return event_id_t ();
   }
 
   auto_delete_vec<checker_event> m_events;
@@ -3206,7 +3217,7 @@ engine::maybe_emit (const candidate_diagnostic &cd)
 			msg);
   expanded_path->add_event (end_of_path);
 
-  expanded_path->set_pending_diagnostic (cd.m_pd);
+  expanded_path->prepare_for_emission (cd.m_pd);
 
   expanded_path->maybe_log (get_logger (), "path for emission");
 
diff --git a/gcc/analyzer/hardcoded-state-machine-malloc.cc b/gcc/analyzer/hardcoded-state-machine-malloc.cc
index 7a8eb52..3124eba 100644
--- a/gcc/analyzer/hardcoded-state-machine-malloc.cc
+++ b/gcc/analyzer/hardcoded-state-machine-malloc.cc
@@ -61,21 +61,39 @@ public:
 
   void emit (rich_location *rich_loc) FINAL OVERRIDE
   {
+    auto_diagnostic_group d;
     metadata m;
     m.add_cwe (415); /* CWE-415: Double Free.  */
     warning_at (rich_loc, m, "double-free of %qE", m_arg);
+
+#if 0
+    if (!rich_loc->get_path ())
+      return;
+
+    event_id_t second_free_event
+      = rich_loc->get_path ()->get_final_event_id ();
+
+    if (m_first_free_event.known_p ()
+	&& second_free_event.known_p ())
+      inform (rich_loc->get_loc (),
+	      "pointer freed at (%i) was already freed at (%i)",
+	      second_free_event.one_based (),
+	      m_first_free_event.one_based ());
+#endif
   }
 
   label_text describe_critical_state_change
     (tree expr,
      state_machine::state_t old_state ATTRIBUTE_UNUSED,
-     state_machine::state_t new_state)
+     state_machine::state_t new_state,
+     event_id_t event_id)
     FINAL OVERRIDE
   {
     if (new_state == m_sm.m_free)
       {
 	pretty_printer pp;
 	pp_printf (&pp, "first %qs here", "free");
+	m_first_free_event = event_id;
 	return label_text::take (xstrdup (pp_formatted_text (&pp)));
 	// TODO: using appropriate colorization etc
       }
@@ -83,7 +101,7 @@ public:
   }
 
   /* FIXME.  */
-  virtual label_text describe_final_event
+  label_text describe_final_event
     (/*diagnostic_context *ctxt, */
      tree expr ATTRIBUTE_UNUSED,
      state_machine::state_t state ATTRIBUTE_UNUSED)
@@ -102,6 +120,10 @@ public:
     return label_text::take (xvsprintf ("freed at (%i)"));
   }
 #endif
+
+private:
+  event_id_t m_first_free_event;
+  //event_id_t m_second_free_event;
 };
 
 class possible_null_deref : public malloc_diagnostic
@@ -120,7 +142,8 @@ public:
 
   label_text describe_critical_state_change (tree expr,
 					     state_machine::state_t old_state,
-					     state_machine::state_t new_state)
+					     state_machine::state_t new_state,
+					     event_id_t event_id)
     FINAL OVERRIDE
   {
     if (old_state == m_sm.m_start && new_state == m_sm.m_unchecked)
@@ -161,7 +184,8 @@ public:
 
   label_text describe_critical_state_change (tree expr,
 					     state_machine::state_t old_state,
-					     state_machine::state_t new_state)
+					     state_machine::state_t new_state,
+					     event_id_t event_id)
     FINAL OVERRIDE
   {
     if (new_state == m_sm.m_free)
@@ -185,7 +209,8 @@ public:
 
   label_text describe_critical_state_change (tree expr,
 					     state_machine::state_t old_state,
-					     state_machine::state_t new_state)
+					     state_machine::state_t new_state,
+					     event_id_t event_id ATTRIBUTE_UNUSED)
     FINAL OVERRIDE
   {
     if (new_state == m_sm.m_unchecked)
diff --git a/gcc/analyzer/hardcoded-state-machine.h b/gcc/analyzer/hardcoded-state-machine.h
index c9bda73..09f6ec1 100644
--- a/gcc/analyzer/hardcoded-state-machine.h
+++ b/gcc/analyzer/hardcoded-state-machine.h
@@ -95,6 +95,27 @@ class metadata : public diagnostic_metadata
  private:
 };
 
+/* FIXME.  */
+
+class event_id_t
+{
+ public:
+  event_id_t () : m_index (UNKNOWN_EVENT_IDX) {}
+  event_id_t (int zero_based_idx) : m_index (zero_based_idx) {}
+
+  bool known_p () const { return m_index != UNKNOWN_EVENT_IDX; }
+
+  int one_based () const
+  {
+    gcc_assert (known_p ());
+    return m_index + 1;
+  }
+
+ private:
+  static const int UNKNOWN_EVENT_IDX = -1;
+  int m_index; // zero-based
+};
+
 /* FIXME:
    Diagnostics are emitted using va_list, which can't be portably stored
    for later use, so we have to make it be a vfunc.  */
@@ -126,7 +147,8 @@ class pending_diagnostic
     (/*diagnostic_context *ctxt, */
      tree expr ATTRIBUTE_UNUSED,
      state_machine::state_t old_state ATTRIBUTE_UNUSED,
-     state_machine::state_t new_state ATTRIBUTE_UNUSED)
+     state_machine::state_t new_state ATTRIBUTE_UNUSED,
+     event_id_t event_id ATTRIBUTE_UNUSED)
   {
     /* Default no-op implementation.  */
     return label_text ();
-- 
1.8.5.3

