aboutsummaryrefslogtreecommitdiffstats
path: root/st.c
diff options
context:
space:
mode:
authorwanabe <wanabe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-10-16 15:12:31 +0000
committerwanabe <wanabe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-10-16 15:12:31 +0000
commit3e946fe3013339bb71fe448efd2b9e597d1902c6 (patch)
tree015373b08169c39c9c022a5c798925aca29c3326 /st.c
parent02689d147d46776a379b8e31cf0c817bf153da9d (diff)
downloadruby-3e946fe3013339bb71fe448efd2b9e597d1902c6.tar.gz
* 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
Diffstat (limited to 'st.c')
-rw-r--r--st.c18
1 files changed, 10 insertions, 8 deletions
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