analyzer: eliminate sm_context::warn_for_state in favor of a new 'warn' vfunc
authorDavid Malcolm <dmalcolm@redhat.com>
Fri, 28 Aug 2020 14:10:38 +0000 (10:10 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Wed, 9 Sep 2020 20:59:32 +0000 (16:59 -0400)
This patch is yet more preliminary work towards generalizing sm-malloc.cc
beyond just malloc/free.

It eliminates sm_context::warn_for_state in terms of a new sm_context::warn
vfunc, guarded by sm_context::get_state calls.

gcc/analyzer/ChangeLog:
* diagnostic-manager.cc
(null_assignment_sm_context::warn_for_state): Replace with...
(null_assignment_sm_context::warn): ...this.
* engine.cc (impl_sm_context::warn_for_state): Replace with...
(impl_sm_context::warn): ...this.
* sm-file.cc (fileptr_state_machine::on_stmt): Replace
warn_for_state and on_transition calls with a get_state
test guarding warn and set_next_state calls.
* sm-malloc.cc (malloc_state_machine::on_stmt): Likewise.
* sm-pattern-test.cc (pattern_test_state_machine::on_condition):
Replace warn_for_state call with warn call.
* sm-sensitive.cc
(sensitive_state_machine::warn_for_any_exposure): Replace
warn_for_state call with a get_state test guarding a warn call.
* sm-signal.cc (signal_state_machine::on_stmt): Likewise.
* sm-taint.cc (taint_state_machine::on_stmt):  Replace
warn_for_state and on_transition calls with a get_state
test guarding warn and set_next_state calls.
* sm.h (sm_context::warn_for_state): Replace with...
(sm_context::warn): ...this.

gcc/analyzer/diagnostic-manager.cc
gcc/analyzer/engine.cc
gcc/analyzer/sm-file.cc
gcc/analyzer/sm-malloc.cc
gcc/analyzer/sm-pattern-test.cc
gcc/analyzer/sm-sensitive.cc
gcc/analyzer/sm-signal.cc
gcc/analyzer/sm-taint.cc
gcc/analyzer/sm.h

index 6fd15c21962b43ea5ee58321b109332d64fb9643..4a95d4c569e360d92d6dbfea522e2451ae17bdb9 100644 (file)
@@ -808,9 +808,8 @@ struct null_assignment_sm_context : public sm_context
                                                        *m_new_state));
   }
 
-  void warn_for_state (const supernode *, const gimple *,
-                      tree, state_machine::state_t,
-                      pending_diagnostic *d) FINAL OVERRIDE
+  void warn (const supernode *, const gimple *,
+            tree, pending_diagnostic *d) FINAL OVERRIDE
   {
     delete d;
   }
index 07b1b15d195e2026095a2ae8030bbb7a06acba91..49701b74fd402d7f1ca90ee27b5fd82f8cf6ef61 100644 (file)
@@ -254,35 +254,23 @@ public:
                           to, origin_new_sval, m_eg.get_ext_state ());
   }
 
-  void warn_for_state (const supernode *snode, const gimple *stmt,
-                      tree var, state_machine::state_t state,
-                      pending_diagnostic *d) FINAL OVERRIDE
+  void warn (const supernode *snode, const gimple *stmt,
+            tree var, pending_diagnostic *d) FINAL OVERRIDE
   {
     LOG_FUNC (get_logger ());
     gcc_assert (d); // take ownership
-
     impl_region_model_context old_ctxt
       (m_eg, m_enode_for_diag, m_old_state, m_new_state, NULL);
-    state_machine::state_t current;
-    if (var)
-      {
-       const svalue *var_old_sval
-         = m_old_state->m_region_model->get_rvalue (var, &old_ctxt);
-       current = m_old_smap->get_state (var_old_sval, m_eg.get_ext_state ());
-      }
-    else
-      current = m_old_smap->get_global_state ();
 
-    if (state == current)
-      {
-       const svalue *var_old_sval
-         = m_old_state->m_region_model->get_rvalue (var, &old_ctxt);
-       m_eg.get_diagnostic_manager ().add_diagnostic
-         (&m_sm, m_enode_for_diag, snode, stmt, m_stmt_finder,
-          var, var_old_sval, state, d);
-      }
-    else
-      delete d;
+    const svalue *var_old_sval
+      = m_old_state->m_region_model->get_rvalue (var, &old_ctxt);
+    state_machine::state_t current
+      = (var
+        ? m_old_smap->get_state (var_old_sval, m_eg.get_ext_state ())
+        : m_old_smap->get_global_state ());
+    m_eg.get_diagnostic_manager ().add_diagnostic
+      (&m_sm, m_enode_for_diag, snode, stmt, m_stmt_finder,
+       var, var_old_sval, current, d);
   }
 
   /* Hook for picking more readable trees for SSA names of temporaries,
index 33b445195d55a8dfce35173f4124db027ba1681b..58a0fd461fa57c88906c4aa0923e6a7efec48a76 100644 (file)
@@ -344,9 +344,12 @@ fileptr_state_machine::on_stmt (sm_context *sm_ctxt,
 
            sm_ctxt->on_transition (node, stmt , arg, m_nonnull, m_closed);
 
-           sm_ctxt->warn_for_state (node, stmt, arg, m_closed,
-                                    new double_fclose (*this, diag_arg));
-           sm_ctxt->on_transition (node, stmt, arg, m_closed, m_stop);
+           if (sm_ctxt->get_state (stmt, arg) == m_closed)
+             {
+               sm_ctxt->warn (node, stmt, arg,
+                              new double_fclose (*this, diag_arg));
+               sm_ctxt->set_next_state (stmt, arg, m_stop);
+             }
            return true;
          }
 
index 19afff4951963c7df3eedc91b0fabdafa3b9362b..2f7db924b946ff341078693371955e11d9f90d12 100644 (file)
@@ -716,14 +716,20 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt,
               we don't want to complain about double-free of NULL.  */
 
            /* freed -> stop, with warning.  */
-           sm_ctxt->warn_for_state (node, stmt, arg, m_freed,
-                                    new double_free (*this, diag_arg));
-           sm_ctxt->on_transition (node, stmt, arg, m_freed, m_stop);
+           if (sm_ctxt->get_state (stmt, arg) == m_freed)
+             {
+               sm_ctxt->warn (node, stmt, arg,
+                              new double_free (*this, diag_arg));
+               sm_ctxt->set_next_state (stmt, arg, m_stop);
+             }
 
            /* non-heap -> stop, with warning.  */
-           sm_ctxt->warn_for_state (node, stmt, arg, m_non_heap,
-                                    new free_of_non_heap (*this, diag_arg));
-           sm_ctxt->on_transition (node, stmt, arg, m_non_heap, m_stop);
+           if (sm_ctxt->get_state (stmt, arg) == m_non_heap)
+             {
+               sm_ctxt->warn (node, stmt, arg,
+                              new free_of_non_heap (*this, diag_arg));
+               sm_ctxt->set_next_state (stmt, arg, m_stop);
+             }
            return true;
          }
 
@@ -744,17 +750,23 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt,
                      || bitmap_bit_p (nonnull_args, i))
                    {
                      tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
-                     sm_ctxt->warn_for_state
-                       (node, stmt, arg, m_unchecked,
-                        new possible_null_arg (*this, diag_arg, callee_fndecl,
-                                               i));
-                     sm_ctxt->on_transition (node, stmt, arg, m_unchecked,
-                                             m_nonnull);
-
-                     sm_ctxt->warn_for_state
-                       (node, stmt, arg, m_null,
-                        new null_arg (*this, diag_arg, callee_fndecl, i));
-                     sm_ctxt->on_transition (node, stmt, arg, m_null, m_stop);
+                     state_t state = sm_ctxt->get_state (stmt, arg);
+                     /* Can't use a switch as the states are non-const.  */
+                     if (state == m_unchecked)
+                       {
+                         sm_ctxt->warn (node, stmt, arg,
+                                        new possible_null_arg (*this, diag_arg,
+                                                               callee_fndecl,
+                                                               i));
+                         sm_ctxt->set_next_state (stmt, arg, m_nonnull);
+                       }
+                     else if (state == m_null)
+                       {
+                         sm_ctxt->warn (node, stmt, arg,
+                                        new null_arg (*this, diag_arg,
+                                                      callee_fndecl, i));
+                         sm_ctxt->set_next_state (stmt, arg, m_stop);
+                       }
                    }
                }
              BITMAP_FREE (nonnull_args);
@@ -800,17 +812,26 @@ malloc_state_machine::on_stmt (sm_context *sm_ctxt,
          tree arg = TREE_OPERAND (op, 0);
          tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
 
-         sm_ctxt->warn_for_state (node, stmt, arg, m_unchecked,
-                                  new possible_null_deref (*this, diag_arg));
-         sm_ctxt->on_transition (node, stmt, arg, m_unchecked, m_nonnull);
-
-         sm_ctxt->warn_for_state (node, stmt, arg, m_null,
-                                  new null_deref (*this, diag_arg));
-         sm_ctxt->on_transition (node, stmt, arg, m_null, m_stop);
-
-         sm_ctxt->warn_for_state (node, stmt, arg, m_freed,
-                                  new use_after_free (*this, diag_arg));
-         sm_ctxt->on_transition (node, stmt, arg, m_freed, m_stop);
+         state_t state = sm_ctxt->get_state (stmt, arg);
+         /* Can't use a switch as the states are non-const.  */
+         if (state == m_unchecked)
+           {
+             sm_ctxt->warn (node, stmt, arg,
+                            new possible_null_deref (*this, diag_arg));
+             sm_ctxt->set_next_state (stmt, arg, m_nonnull);
+           }
+         else if (state == m_null)
+           {
+             sm_ctxt->warn (node, stmt, arg,
+                            new null_deref (*this, diag_arg));
+             sm_ctxt->set_next_state (stmt, arg, m_stop);
+           }
+         else if (state == m_freed)
+           {
+             sm_ctxt->warn (node, stmt, arg,
+                            new use_after_free (*this, diag_arg));
+             sm_ctxt->set_next_state (stmt, arg, m_stop);
+           }
        }
     }
   return false;
index 6a59e8fff83fb4b48324862fd3fb98fd0ed1102a..bb6d3b1e719687594cbff937726e774bbfd8b574 100644 (file)
@@ -128,7 +128,7 @@ pattern_test_state_machine::on_condition (sm_context *sm_ctxt,
     return;
 
   pending_diagnostic *diag = new pattern_match (lhs, op, rhs);
-  sm_ctxt->warn_for_state (node, stmt, lhs, m_start, diag);
+  sm_ctxt->warn (node, stmt, lhs, diag);
 }
 
 bool
index f10008307af8609c463d3343857ba38814b5afb3..49f9eb387b19a6377ae4e7e8aea678bc54b8d110 100644 (file)
@@ -174,8 +174,9 @@ sensitive_state_machine::warn_for_any_exposure (sm_context *sm_ctxt,
                                                tree arg) const
 {
   tree diag_arg = sm_ctxt->get_diagnostic_tree (arg);
-  sm_ctxt->warn_for_state (node, stmt, arg, m_sensitive,
-                          new exposure_through_output_file (*this, diag_arg));
+  if (sm_ctxt->get_state (stmt, arg) == m_sensitive)
+    sm_ctxt->warn (node, stmt, arg,
+                  new exposure_through_output_file (*this, diag_arg));
 }
 
 /* Implementation of state_machine::on_stmt vfunc for
index 21c9d58f6deff2bd2d3f4049adde39c838425a4d..bf6ea4804238388963a75136287c36bba4f1bf63 100644 (file)
@@ -346,9 +346,10 @@ signal_state_machine::on_stmt (sm_context *sm_ctxt,
       if (const gcall *call = dyn_cast <const gcall *> (stmt))
        if (tree callee_fndecl = sm_ctxt->get_fndecl_for_call (call))
          if (signal_unsafe_p (callee_fndecl))
-           sm_ctxt->warn_for_state (node, stmt, NULL_TREE, m_in_signal_handler,
-                                    new signal_unsafe_call (*this, call,
-                                                            callee_fndecl));
+           if (sm_ctxt->get_global_state () == m_in_signal_handler)
+             sm_ctxt->warn (node, stmt, NULL_TREE,
+                            new signal_unsafe_call (*this, call,
+                                                    callee_fndecl));
     }
 
   return false;
index 385909ce26c17152cb14ceff0ab7c05583560989..49bbd6dfb131c01390da51f1036f94e5e60ce005 100644 (file)
@@ -233,27 +233,36 @@ taint_state_machine::on_stmt (sm_context *sm_ctxt,
          if (INTEGRAL_TYPE_P (TREE_TYPE (arg)))
            is_unsigned = TYPE_UNSIGNED (TREE_TYPE (arg));
 
-         /* Complain about missing bounds.  */
-         sm_ctxt->warn_for_state
-           (node, stmt, arg, m_tainted,
-            new tainted_array_index (*this, diag_arg,
-                                     is_unsigned
-                                     ? BOUNDS_LOWER : BOUNDS_NONE));
-         sm_ctxt->on_transition (node, stmt, arg, m_tainted, m_stop);
-
-         /* Complain about missing upper bound.  */
-         sm_ctxt->warn_for_state  (node, stmt, arg, m_has_lb,
-                                   new tainted_array_index (*this, diag_arg,
-                                                            BOUNDS_LOWER));
-         sm_ctxt->on_transition (node, stmt, arg, m_has_lb, m_stop);
-
-         /* Complain about missing lower bound.  */
-         if (!is_unsigned)
+         state_t state = sm_ctxt->get_state (stmt, arg);
+         /* Can't use a switch as the states are non-const.  */
+         if (state == m_tainted)
            {
-             sm_ctxt->warn_for_state  (node, stmt, arg, m_has_ub,
-                                       new tainted_array_index (*this, diag_arg,
-                                                                BOUNDS_UPPER));
-             sm_ctxt->on_transition (node, stmt, arg, m_has_ub, m_stop);
+             /* Complain about missing bounds.  */
+             pending_diagnostic *d
+               = new tainted_array_index (*this, diag_arg,
+                                          is_unsigned
+                                          ? BOUNDS_LOWER : BOUNDS_NONE);
+             sm_ctxt->warn (node, stmt, arg, d);
+             sm_ctxt->set_next_state (stmt, arg, m_stop);
+           }
+         else if (state == m_has_lb)
+           {
+             /* Complain about missing upper bound.  */
+             sm_ctxt->warn (node, stmt, arg,
+                             new tainted_array_index (*this, diag_arg,
+                                                      BOUNDS_LOWER));
+             sm_ctxt->set_next_state (stmt, arg, m_stop);
+           }
+         else if (state == m_has_ub)
+           {
+             /* Complain about missing lower bound.  */
+             if (!is_unsigned)
+               {
+                 sm_ctxt->warn  (node, stmt, arg,
+                                 new tainted_array_index (*this, diag_arg,
+                                                          BOUNDS_UPPER));
+                 sm_ctxt->set_next_state (stmt, arg, m_stop);
+               }
            }
        }
     }
index c5071464994f009d5e5579186adf5393bd7e93d1..740cbecd7a9f0d5734da702db8799a4cbdc1bed5 100644 (file)
@@ -198,11 +198,9 @@ public:
   }
 
   /* Called by state_machine in response to pattern matches:
-     issue a diagnostic D if VAR is in state STATE, using NODE and STMT
-     for location information.  */
-  virtual void warn_for_state (const supernode *node, const gimple *stmt,
-                              tree var, state_machine::state_t state,
-                              pending_diagnostic *d) = 0;
+     issue a diagnostic D using NODE and STMT for location information.  */
+  virtual void warn (const supernode *node, const gimple *stmt,
+                    tree var, pending_diagnostic *d) = 0;
 
   /* For use when generating trees when creating pending_diagnostics, so that
      rather than e.g.