From 18056e45db1c75aa209fa9a756395ddceb867a88 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Mon, 31 Aug 2020 09:00:23 -0400 Subject: [PATCH] analyzer: fix ICE on unknown index in CONSTRUCTOR [PR96860] 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 | 3 ++- gcc/analyzer/store.cc | 33 ++++++++++++++++------- gcc/analyzer/store.h | 6 ++--- gcc/testsuite/gcc.dg/analyzer/pr96860-1.c | 9 +++++++ gcc/testsuite/gcc.dg/analyzer/pr96860-2.c | 8 ++++++ 5 files changed, 45 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr96860-1.c create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr96860-2.c diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index 1823901a3ee..53f32dc912c 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -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); diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc index 8890a69a6f8..7f15aa92492 100644 --- a/gcc/analyzer/store.cc +++ b/gcc/analyzer/store.cc @@ -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; } } diff --git a/gcc/analyzer/store.h b/gcc/analyzer/store.h index 0ac93179dc6..83a43107b21 100644 --- a/gcc/analyzer/store.h +++ b/gcc/analyzer/store.h @@ -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 index 00000000000..8f298ec04e7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96860-1.c @@ -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 index 00000000000..90a818cb283 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr96860-2.c @@ -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, + }; +} -- 2.30.2