From 00cb0f5840795698557731c6e549a5ce99573223 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 20 Aug 2020 10:00:49 -0400 Subject: [PATCH] analyzer: fix infinite recursion ICE on unions [PR96723] Attempts to store sm-state into a union in C++ triggered an infinite recursion when trying to generate a representative tree, due to erroneously trying to use the dtor of the union as a field. Fix it by filtering out non-FIELD_DECLs when walking TYPE_FIELDs in region::get_subregions_for_binding. gcc/analyzer/ChangeLog: PR analyzer/96723 * region-model-manager.cc (region_model_manager::get_field_region): Assert that field is a FIELD_DECL. * region.cc (region::get_subregions_for_binding): In union-handling, filter the TYPE_FIELDS traversal to just FIELD_DECLs. gcc/testsuite/ChangeLog: PR analyzer/96723 * g++.dg/analyzer/pr96723.C: New test. --- gcc/analyzer/region-model-manager.cc | 2 ++ gcc/analyzer/region.cc | 2 ++ gcc/testsuite/g++.dg/analyzer/pr96723.C | 10 ++++++++++ 3 files changed, 14 insertions(+) create mode 100644 gcc/testsuite/g++.dg/analyzer/pr96723.C diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc index 422c4a95e7b..75402649a91 100644 --- a/gcc/analyzer/region-model-manager.cc +++ b/gcc/analyzer/region-model-manager.cc @@ -781,6 +781,8 @@ region_model_manager::get_region_for_global (tree expr) const region * region_model_manager::get_field_region (const region *parent, tree field) { + gcc_assert (TREE_CODE (field) == FIELD_DECL); + field_region::key_t key (parent, field); if (field_region *reg = m_field_regions.get (key)) return reg; diff --git a/gcc/analyzer/region.cc b/gcc/analyzer/region.cc index c3dc8cdfa84..1823901a3ee 100644 --- a/gcc/analyzer/region.cc +++ b/gcc/analyzer/region.cc @@ -311,6 +311,8 @@ region::get_subregions_for_binding (region_model_manager *mgr, for (tree field = TYPE_FIELDS (get_type ()); field != NULL_TREE; field = DECL_CHAIN (field)) { + if (TREE_CODE (field) != FIELD_DECL) + continue; const region *subregion = mgr->get_field_region (this, field); subregion->get_subregions_for_binding (mgr, relative_bit_offset, diff --git a/gcc/testsuite/g++.dg/analyzer/pr96723.C b/gcc/testsuite/g++.dg/analyzer/pr96723.C new file mode 100644 index 00000000000..5d9980c9d2d --- /dev/null +++ b/gcc/testsuite/g++.dg/analyzer/pr96723.C @@ -0,0 +1,10 @@ +void +foo () +{ + union + { + int *p; + } u; + u.p = new int; + delete u.p; +} -- 2.30.2