]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
analyzer: fix ICE on unknown index in CONSTRUCTOR [PR96860]
authorDavid Malcolm <dmalcolm@redhat.com>
Mon, 31 Aug 2020 13:00:23 +0000 (09:00 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Mon, 31 Aug 2020 22:28:59 +0000 (18:28 -0400)
PR analyzer/96860 reports an ICE inside CONSTRUCTOR-handling with
--param analyzer-max-svalue-depth=0 when attempting to build a
binding_map for the CONSTRUCTOR's values.

The issue is that when handling (index, value) pairs for initializing
an array, the index values for the elements exceeds the svalue
complexity limit, and the index is thus treated as unknown, leading to
a symbolic rather than concrete offset for each array element.

This patch updates the CONSTRUCTOR-handling code so that it can
fail, returning an unknown value for the overall value of the
constructor for this case, fixing the ICE.

gcc/analyzer/ChangeLog:
PR analyzer/96860
* region.cc (decl_region::get_svalue_for_constructor): Support
apply_ctor_to_region failing.
* store.cc (binding_map::apply_ctor_to_region): Add failure
handling.
(binding_map::apply_ctor_val_to_range): Likewise.
(binding_map::apply_ctor_pair_to_child_region): Likewise.  Replace
assertion that child_base_offset is not symbolic with error
handling.
* store.h (binding_map::apply_ctor_to_region): Convert return type
from void to bool.
(binding_map::apply_ctor_val_to_range): Likewise.
(binding_map::apply_ctor_pair_to_child_region): Likewise.

gcc/testsuite/ChangeLog:
PR analyzer/96860
* gcc.dg/analyzer/pr96860-1.c: New test.
* gcc.dg/analyzer/pr96860-2.c: New test.

gcc/analyzer/region.cc
gcc/analyzer/store.cc
gcc/analyzer/store.h
gcc/testsuite/gcc.dg/analyzer/pr96860-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/pr96860-2.c [new file with mode: 0644]

index 1823901a3eeb47737b5d126c71769e6ac3b20d12..53f32dc912c12fa591ba73162e9bd476e908d256 100644 (file)
@@ -904,7 +904,8 @@ decl_region::get_svalue_for_constructor (tree ctor,
      decl_region as the base region when building child regions
      for offset calculations.  */
   binding_map map;
-  map.apply_ctor_to_region (this, ctor, mgr);
+  if (!map.apply_ctor_to_region (this, ctor, mgr))
+    return mgr->get_or_create_unknown_svalue (get_type ());
 
   /* Return a compound svalue for the map we built.  */
   return mgr->get_or_create_compound_svalue (get_type (), map);
index 8890a69a6f80b93fb97e006fcc5ee75faa3d20fb..7f15aa92492977e957d5747dcaaf7e8661f76e52 100644 (file)
@@ -402,9 +402,11 @@ get_svalue_for_ctor_val (tree val, region_model_manager *mgr)
 }
 
 /* Bind values from CONSTRUCTOR to this map, relative to
-   PARENT_REG's relationship to its base region.  */
+   PARENT_REG's relationship to its base region.
+   Return true if successful, false if there was a problem (e.g. due
+   to hitting a complexity limit).  */
 
-void
+bool
 binding_map::apply_ctor_to_region (const region *parent_reg, tree ctor,
                                   region_model_manager *mgr)
 {
@@ -423,18 +425,24 @@ binding_map::apply_ctor_to_region (const region *parent_reg, tree ctor,
        {
          tree min_index = TREE_OPERAND (index, 0);
          tree max_index = TREE_OPERAND (index, 1);
-         apply_ctor_val_to_range (parent_reg, mgr, min_index, max_index, val);
+         if (!apply_ctor_val_to_range (parent_reg, mgr,
+                                       min_index, max_index, val))
+           return false;
          continue;
        }
-      apply_ctor_pair_to_child_region (parent_reg, mgr, index, val);
+      if (!apply_ctor_pair_to_child_region (parent_reg, mgr, index, val))
+       return false;
     }
+  return true;
 }
 
 /* Bind the value VAL into the range of elements within PARENT_REF
    from MIN_INDEX to MAX_INDEX (including endpoints).
-   For use in handling RANGE_EXPR within a CONSTRUCTOR.  */
+   For use in handling RANGE_EXPR within a CONSTRUCTOR.
+   Return true if successful, false if there was a problem (e.g. due
+   to hitting a complexity limit).  */
 
-void
+bool
 binding_map::apply_ctor_val_to_range (const region *parent_reg,
                                      region_model_manager *mgr,
                                      tree min_index, tree max_index,
@@ -469,12 +477,15 @@ binding_map::apply_ctor_val_to_range (const region *parent_reg,
 
   /* Bind the value to the range.  */
   put (range_key, sval);
+  return true;
 }
 
 /* Bind the value VAL into INDEX within PARENT_REF.
-   For use in handling a pair of entries within a CONSTRUCTOR.  */
+   For use in handling a pair of entries within a CONSTRUCTOR.
+   Return true if successful, false if there was a problem (e.g. due
+   to hitting a complexity limit).  */
 
-void
+bool
 binding_map::apply_ctor_pair_to_child_region (const region *parent_reg,
                                              region_model_manager *mgr,
                                              tree index, tree val)
@@ -482,7 +493,7 @@ binding_map::apply_ctor_pair_to_child_region (const region *parent_reg,
   const region *child_reg
     = get_subregion_within_ctor (parent_reg, index, mgr);
   if (TREE_CODE (val) == CONSTRUCTOR)
-    apply_ctor_to_region (child_reg, val, mgr);
+    return apply_ctor_to_region (child_reg, val, mgr);
   else
     {
       const svalue *sval = get_svalue_for_ctor_val (val, mgr);
@@ -502,7 +513,8 @@ binding_map::apply_ctor_pair_to_child_region (const region *parent_reg,
          bit_size_t sval_bit_size = sval_byte_size * BITS_PER_UNIT;
          /* Get offset of child relative to base region.  */
          region_offset child_base_offset = child_reg->get_offset ();
-         gcc_assert (!child_base_offset.symbolic_p ());
+         if (child_base_offset.symbolic_p ())
+           return false;
          /* Convert to an offset relative to the parent region.  */
          region_offset parent_base_offset = parent_reg->get_offset ();
          gcc_assert (!parent_base_offset.symbolic_p ());
@@ -515,6 +527,7 @@ binding_map::apply_ctor_pair_to_child_region (const region *parent_reg,
        }
       gcc_assert (k->concrete_p ());
       put (k, sval);
+      return true;
     }
 }
 
index 0ac93179dc6fa4686e13dc3592889c8091835da9..83a43107b218b2a375dc8e62b9230bdf251f0eec 100644 (file)
@@ -340,15 +340,15 @@ public:
   void dump_to_pp (pretty_printer *pp, bool simple, bool multiline) const;
   void dump (bool simple) const;
 
-  void apply_ctor_to_region (const region *parent_reg, tree ctor,
+  bool apply_ctor_to_region (const region *parent_reg, tree ctor,
                             region_model_manager *mgr);
 
 private:
-  void apply_ctor_val_to_range (const region *parent_reg,
+  bool apply_ctor_val_to_range (const region *parent_reg,
                                region_model_manager *mgr,
                                tree min_index, tree max_index,
                                tree val);
-  void apply_ctor_pair_to_child_region (const region *parent_reg,
+  bool apply_ctor_pair_to_child_region (const region *parent_reg,
                                        region_model_manager *mgr,
                                        tree index, tree val);
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c b/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c
new file mode 100644 (file)
index 0000000..8f298ec
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-require-effective-target int128 } */
+/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */
+
+void x7 (void)
+{
+  __int128 z5[] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1,
+  };
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c b/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c
new file mode 100644 (file)
index 0000000..90a818c
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-additional-options "--param analyzer-max-svalue-depth=0" } */
+
+void x7 (void)
+{
+  long z5[] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1,
+  };
+}