Do not save hash slots across calls to hash_table::get_or_insert.
authorAldy Hernandez <aldyh@redhat.com>
Tue, 13 Oct 2020 08:40:20 +0000 (04:40 -0400)
committerAldy Hernandez <aldyh@redhat.com>
Tue, 13 Oct 2020 15:02:18 +0000 (11:02 -0400)
commit739526a19deaeac19c2429cc7567052834d3098e
tree58dac36fb9f3a16da4574f9566d44d06a33c7836
parent8311899eddf91d0d3e3ad931c6bbf2d5a1b445ca
Do not save hash slots across calls to hash_table::get_or_insert.

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.

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