]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
analyzer: fix ICEs seen with call summaries on PR 107060
authorDavid Malcolm <dmalcolm@redhat.com>
Wed, 5 Oct 2022 17:52:59 +0000 (13:52 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Wed, 5 Oct 2022 17:52:59 +0000 (13:52 -0400)
This doesn't fix the various false positives seen with
-fanalyzer-call-summaries on PR 107060, but stops it crashing at -O2.

gcc/analyzer/ChangeLog:
PR analyzer/107060
* call-summary.cc
(call_summary_replay::convert_svalue_from_summary_1): Handle NULL
results from convert_svalue_from_summary in SK_UNARY_OP and
SK_BIN_OP.
* engine.cc (impl_region_model_context::on_unknown_change): Bail
out on svalues that can't have associated state.
* region-model-impl-calls.cc
(region_model::impl_call_analyzer_get_unknown_ptr): New.
* region-model.cc (region_model::on_stmt_pre): Handle
"__analyzer_get_unknown_ptr".
* region-model.h
(region_model::impl_call_analyzer_get_unknown_ptr): New decl.
* store.cc (store::replay_call_summary_cluster): Avoid trying to
create binding clusters for base regions that shouldn't have them.

gcc/ChangeLog:
PR analyzer/107060
* doc/analyzer.texi (__analyzer_get_unknown_ptr): Document.

gcc/testsuite/ChangeLog:
PR analyzer/107060
* gcc.dg/analyzer/analyzer-decls.h (__analyzer_get_unknown_ptr):
New decl.
* gcc.dg/analyzer/call-summaries-2.c
(test_summarized_writes_param_to_ptr_unknown): New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
gcc/analyzer/call-summary.cc
gcc/analyzer/engine.cc
gcc/analyzer/region-model-impl-calls.cc
gcc/analyzer/region-model.cc
gcc/analyzer/region-model.h
gcc/analyzer/store.cc
gcc/doc/analyzer.texi
gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h
gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c

index a8e881472ea3bcdb618243d6c75efe881e031624..33916547e1efe5ff55fa05bd95ba1c8087e234d6 100644 (file)
@@ -298,23 +298,33 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
       {
        const unaryop_svalue *unaryop_summary_sval
          = as_a <const unaryop_svalue *> (summary_sval);
+       const svalue *summary_arg = unaryop_summary_sval->get_arg ();
+       const svalue *caller_arg = convert_svalue_from_summary (summary_arg);
+       if (!caller_arg)
+         return NULL;
        region_model_manager *mgr = get_manager ();
-       return mgr->get_or_create_unaryop
-         (summary_sval->get_type (),
-          unaryop_summary_sval->get_op (),
-          convert_svalue_from_summary (unaryop_summary_sval->get_arg ()));
+       return mgr->get_or_create_unaryop (summary_sval->get_type (),
+                                          unaryop_summary_sval->get_op (),
+                                          caller_arg);
       }
       break;
     case SK_BINOP:
       {
        const binop_svalue *binop_summary_sval
          = as_a <const binop_svalue *> (summary_sval);
+       const svalue *summary_arg0 = binop_summary_sval->get_arg0 ();
+       const svalue *caller_arg0 = convert_svalue_from_summary (summary_arg0);
+       if (!caller_arg0)
+         return NULL;
+       const svalue *summary_arg1 = binop_summary_sval->get_arg1 ();
+       const svalue *caller_arg1 = convert_svalue_from_summary (summary_arg1);
+       if (!caller_arg1)
+         return NULL;
        region_model_manager *mgr = get_manager ();
-       return mgr->get_or_create_binop
-         (summary_sval->get_type (),
-          binop_summary_sval->get_op (),
-          convert_svalue_from_summary (binop_summary_sval->get_arg0 ()),
-          convert_svalue_from_summary (binop_summary_sval->get_arg1 ()));
+       return mgr->get_or_create_binop (summary_sval->get_type (),
+                                        binop_summary_sval->get_op (),
+                                        caller_arg0,
+                                        caller_arg1);
       }
       break;
     case SK_SUB:
index 735b5a3c0614612b31789abd34dc2cdd8b46f56a..faef0bd15b01f1b059bdd36efe876617dcf3265e 100644 (file)
@@ -172,6 +172,8 @@ void
 impl_region_model_context::on_unknown_change (const svalue *sval,
                                              bool is_mutable)
 {
+  if (!sval->can_have_associated_state_p ())
+    return;
   for (sm_state_map *smap : m_new_state->m_checker_states)
     smap->on_unknown_change (sval, is_mutable, m_ext_state);
 }
index 71fb2770143224c72387824b06b48e16d3c07f98..5cc590716b4fcdf01e2e6f96ac208ebf6b814be8 100644 (file)
@@ -374,6 +374,16 @@ region_model::impl_call_analyzer_eval (const gcall *call,
   warning_at (call->location, 0, "%s", t.as_string ());
 }
 
+/* Handle the on_call_pre part of "__analyzer_get_unknown_ptr".  */
+
+void
+region_model::impl_call_analyzer_get_unknown_ptr (const call_details &cd)
+{
+  const svalue *ptr_sval
+    = m_mgr->get_or_create_unknown_svalue (cd.get_lhs_type ());
+  cd.maybe_set_lhs (ptr_sval);
+}
+
 /* Handle the on_call_pre part of "__builtin_expect" etc.  */
 
 void
index d14f3a1840e7213b8f2248447b154d5b8510166d..aa3d2054131f709c1eef4d0bac6fe5c0539cc2b9 100644 (file)
@@ -1256,6 +1256,12 @@ region_model::on_stmt_pre (const gimple *stmt,
          {
            /* This is handled elsewhere.  */
          }
+       else if (is_special_named_call_p (call, "__analyzer_get_unknown_ptr",
+                                         0))
+         {
+           call_details cd (call, this, ctxt);
+           impl_call_analyzer_get_unknown_ptr (cd);
+         }
        else
          *out_unknown_side_effects = on_call_pre (call, ctxt,
                                                   out_terminate_path);
index 6903090fcd3b6578e987bb37e8856eb35602e040..e81595e8bc4f84e343f988afd60a60716b8cac94 100644 (file)
@@ -344,6 +344,7 @@ class region_model
   void impl_call_analyzer_dump_escaped (const gcall *call);
   void impl_call_analyzer_eval (const gcall *call,
                                region_model_context *ctxt);
+  void impl_call_analyzer_get_unknown_ptr (const call_details &cd);
   void impl_call_builtin_expect (const call_details &cd);
   void impl_call_calloc (const call_details &cd);
   bool impl_call_error (const call_details &cd, unsigned min_args,
index 74b481dce48da44b53e587fc6dbaab53e45bcafc..1ca12142e47169396b3813a491a0c83ae9a0f3fb 100644 (file)
@@ -3176,12 +3176,16 @@ store::replay_call_summary_cluster (call_summary_replay &r,
        = r.convert_region_from_summary (summary_base_reg))
       {
        const region *caller_base_reg = caller_reg->get_base_region ();
-       binding_cluster *caller_cluster
-         = get_or_create_cluster (caller_base_reg);
-       if (summary_cluster->escaped_p ())
-         caller_cluster->mark_as_escaped ();
-       if (summary_cluster->touched_p ())
-         caller_cluster->m_touched = true;
+       if (caller_base_reg->tracked_p ()
+           && !caller_base_reg->symbolic_for_unknown_ptr_p ())
+         {
+           binding_cluster *caller_cluster
+             = get_or_create_cluster (caller_base_reg);
+           if (summary_cluster->escaped_p ())
+             caller_cluster->mark_as_escaped ();
+           if (summary_cluster->touched_p ())
+             caller_cluster->m_touched = true;
+         }
       }
 
   switch (summary_base_reg->get_kind ())
index 06eb98fe4d3065aa07f4f596c70731b40b5e20b1..ec49f951435d4a3b6fc3cf37e58b6042748d43ca 100644 (file)
@@ -544,6 +544,10 @@ __analyzer_eval (expr);
 will emit a warning with text "TRUE", FALSE" or "UNKNOWN" based on the
 truthfulness of the argument.  This is useful for writing DejaGnu tests.
 
+@smallexample
+__analyzer_get_unknown_ptr ();
+@end smallexample
+will obtain an unknown @code{void *}.
 
 @subsection Other Debugging Techniques
 
index d05257949ff215197f323456b216aac1a1c191fd..4478d740b58cc48795c014b5473e996b74eea8ab 100644 (file)
@@ -47,4 +47,7 @@ extern void __analyzer_dump_state (const char *name, ...);
    truthfulness of the argument.  */
 extern void __analyzer_eval (int);
 
+/* Obtain an "unknown" void *.  */
+extern void *__analyzer_get_unknown_ptr (void);
+
 #endif /* #ifndef ANALYZER_DECLS_H.  */
index 0aaf67b8fd473a1db78e0e7ace0c9ecb091d7442..85cece72b3440c30db0ad952fce401ce4ca53e04 100644 (file)
@@ -72,6 +72,13 @@ void test_summarized_writes_param_to_ptr (int j)
   __analyzer_eval (y == j); /* { dg-warning "TRUE" } */
 }
 
+void test_summarized_writes_param_to_ptr_unknown (int j)
+{
+  int *p = (int *)__analyzer_get_unknown_ptr ();
+  writes_param_to_ptr (j, p);
+  __analyzer_eval (*p == j); /* { dg-warning "UNKNOWN" } */
+}
+
 int g;
 
 void writes_to_global (int i)