[PUSHED] ranger: Do not save hash slots across calls to hash_table::get_or_insert.
Aldy Hernandez
aldyh@redhat.com
Tue Oct 13 15:06:04 GMT 2020
There's a read of a freed block while accessing the default_slot in
calc_switch_ranges.
default_slot->intersect (def_range);
It seems the default_slot got swiped from under us, and the valgrind
dump indicates the free came from the get_or_insert in the same
function:
irange *&slot = m_edge_table->get_or_insert (e, &existed);
So it looks like the get_or_insert is actually freeing the value of
the previously allocated default_slot. Looking down the chain
from get_or_insert, we see it calls hash_table<>::expand, which
actually does a free while doing a resize of sorts:
if (!m_ggc)
Allocator <value_type> ::data_free (oentries);
else
ggc_free (oentries);
This patch avoids keeping a pointer to the default_slot across multiple
calls to get_or_insert in the loop.
Pushed.
gcc/ChangeLog:
PR tree-optimization/97379
* gimple-range-edge.cc (outgoing_range::calc_switch_ranges): Do
not save hash slot across calls to hash_table<>::get_or_insert.
---
gcc/gimple-range-edge.cc | 24 ++++++++++++------------
1 file changed, 12 insertions(+), 12 deletions(-)
diff --git a/gcc/gimple-range-edge.cc b/gcc/gimple-range-edge.cc
index c5ee54fec51..b42dcd6d318 100644
--- a/gcc/gimple-range-edge.cc
+++ b/gcc/gimple-range-edge.cc
@@ -106,19 +106,14 @@ outgoing_range::calc_switch_ranges (gswitch *sw)
unsigned x, lim;
lim = gimple_switch_num_labels (sw);
tree type = TREE_TYPE (gimple_switch_index (sw));
-
edge default_edge = gimple_switch_default_edge (cfun, sw);
- irange *&default_slot = m_edge_table->get_or_insert (default_edge, &existed);
- // This should be the first call into this switch. For the default
- // range case, start with varying and intersect each other case from
- // it.
-
- gcc_checking_assert (!existed);
-
- // Allocate an int_range_max for default case.
- default_slot = m_range_allocator.allocate (255);
- default_slot->set_varying (type);
+ // This should be the first call into this switch.
+ //
+ // Allocate an int_range_max for the default range case, start with
+ // varying and intersect each other case from it.
+ irange *default_range = m_range_allocator.allocate (255);
+ default_range->set_varying (type);
for (x = 1; x < lim; x++)
{
@@ -137,7 +132,7 @@ outgoing_range::calc_switch_ranges (gswitch *sw)
int_range_max def_range (low, high);
range_cast (def_range, type);
def_range.invert ();
- default_slot->intersect (def_range);
+ default_range->intersect (def_range);
// Create/union this case with anything on else on the edge.
int_range_max case_range (low, high);
@@ -157,6 +152,11 @@ outgoing_range::calc_switch_ranges (gswitch *sw)
// intrusive than allocating max ranges for each case.
slot = m_range_allocator.allocate (case_range);
}
+
+ irange *&slot = m_edge_table->get_or_insert (default_edge, &existed);
+ // This should be the first call into this switch.
+ gcc_checking_assert (!existed);
+ slot = default_range;
}
--
2.26.2
More information about the Gcc-patches
mailing list