From 3e946fe3013339bb71fe448efd2b9e597d1902c6 Mon Sep 17 00:00:00 2001 From: wanabe Date: Fri, 16 Oct 2009 15:12:31 +0000 Subject: * st.c (unpack_entries): save table->bins and never change the table during unpacking. Because st_insert() may cause GC and refer the table, i.e. st_foreach(). [Bug #2196] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25377 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 6 ++++++ st.c | 18 ++++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 30299a20a6..128f292c7a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +Fri Oct 17 00:05:53 2009 wanabe + + * st.c (unpack_entries): save table->bins and never change the table + during unpacking. Because st_insert() may cause GC and refer the + table, i.e. st_foreach(). [Bug #2196] + Fri Oct 16 22:20:25 2009 Tanaka Akira * prelude.rb (require_relative): defined as a module function of diff --git a/st.c b/st.c index 1974113fb2..fe8913bcc5 100644 --- a/st.c +++ b/st.c @@ -418,15 +418,17 @@ unpack_entries(register st_table *table) { int i; struct st_table_entry *packed_bins[MAX_PACKED_NUMHASH*2]; - int num_entries = table->num_entries; - - memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * num_entries*2); - table->entries_packed = 0; - table->num_entries = 0; - memset(table->bins, 0, sizeof(struct st_table_entry *) * table->num_bins); - for (i = 0; i < num_entries; i++) { - st_insert(table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]); + st_table tmp_table = *table; + + memcpy(packed_bins, table->bins, sizeof(struct st_table_entry *) * table->num_entries*2); + table->bins = packed_bins; + tmp_table.entries_packed = 0; + tmp_table.num_entries = 0; + memset(tmp_table.bins, 0, sizeof(struct st_table_entry *) * tmp_table.num_bins); + for (i = 0; i < table->num_entries; i++) { + st_insert(&tmp_table, (st_data_t)packed_bins[i*2], (st_data_t)packed_bins[i*2+1]); } + *table = tmp_table; } int -- cgit v1.2.3