[前][次][番号順一覧][スレッド一覧]

ruby-changes:73874

From: Peter <ko1@a...>
Date: Thu, 6 Oct 2022 22:01:35 +0900 (JST)
Subject: [ruby-changes:73874] 76bae60d9b (master): [Bug #19038] Fix corruption of generic_iv_tbl when compacting

https://git.ruby-lang.org/ruby.git/commit/?id=76bae60d9b

From 76bae60d9b967415c5930c2c5906e14c8362a6dd Mon Sep 17 00:00:00 2001
From: Peter Zhu <peter@p...>
Date: Wed, 5 Oct 2022 15:19:43 -0400
Subject: [Bug #19038] Fix corruption of generic_iv_tbl when compacting

When the generic_iv_tbl is resized up, rebuild_table performs
allocations that can trigger GC. If autocompaction is enabled, then
moved objects are removed from and inserted into the generic_iv_tbl.
This may cause another call to rebuild_table to resize the
generic_iv_tbl. When returning back to the original rebuild_table, some
of the data may be stale, causing the generic_iv_tbl to be corrupted.

This commit changes rebuild_table to only read data from the st_table
after the allocations have completed.

Co-Authored-By: Matt Valentine-House <matt@e...>
---
 st.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/st.c b/st.c
index 6b534a856a..cffcde273c 100644
--- a/st.c
+++ b/st.c
@@ -703,16 +703,14 @@ count_collision(const struct st_hash_type *type) https://github.com/ruby/ruby/blob/trunk/st.c#L703
 static void
 rebuild_table(st_table *tab)
 {
-    st_index_t i, ni, bound;
+    st_index_t i, ni;
     unsigned int size_ind;
     st_table *new_tab;
-    st_table_entry *entries, *new_entries;
+    st_table_entry *new_entries;
     st_table_entry *curr_entry_ptr;
     st_index_t *bins;
     st_index_t bin_ind;
 
-    bound = tab->entries_bound;
-    entries = tab->entries;
     if ((2 * tab->num_entries <= get_allocated_entries(tab)
          && REBUILD_THRESHOLD * tab->num_entries > get_allocated_entries(tab))
         || tab->num_entries < (1 << MINIMAL_POWER2)) {
@@ -721,16 +719,23 @@ rebuild_table(st_table *tab) https://github.com/ruby/ruby/blob/trunk/st.c#L719
         if (tab->bins != NULL)
             initialize_bins(tab);
         new_tab = tab;
-        new_entries = entries;
+        new_entries = tab->entries;
     }
     else {
+        /* This allocation could trigger GC and compaction. If tab is the
+         * gen_iv_tbl, then tab could have changed in size due to objects being
+         * freed and/or moved. Do not store attributes of tab before this line. */
         new_tab = st_init_table_with_size(tab->type,
                                           2 * tab->num_entries - 1);
         new_entries = new_tab->entries;
     }
+
     ni = 0;
     bins = new_tab->bins;
     size_ind = get_size_ind(new_tab);
+    st_index_t bound = tab->entries_bound;
+    st_table_entry *entries = tab->entries;
+
     for (i = tab->entries_start; i < bound; i++) {
         curr_entry_ptr = &entries[i];
         PREFETCH(entries + i + 1, 0);
-- 
cgit v1.2.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]