ruby-changes:73993
From: nagachika <ko1@a...>
Date: Sat, 15 Oct 2022 15:41:15 +0900 (JST)
Subject: [ruby-changes:73993] 830fbb412b (ruby_3_1): merge revision(s) 76bae60d9b967415c5930c2c5906e14c8362a6dd: [Backport #19038]
https://git.ruby-lang.org/ruby.git/commit/?id=830fbb412b From 830fbb412b1c01f0a44b66a70b946d7e87feb6e5 Mon Sep 17 00:00:00 2001 From: nagachika <nagachika@r...> Date: Sat, 15 Oct 2022 15:40:47 +0900 Subject: merge revision(s) 76bae60d9b967415c5930c2c5906e14c8362a6dd: [Backport #19038] [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(-) --- st.c | 21 +++++++++++++-------- version.h | 4 ++-- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/st.c b/st.c index 07a083abb0..fb36a452f5 100644 --- a/st.c +++ b/st.c @@ -703,34 +703,39 @@ 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)) { /* Compaction: */ tab->num_entries = 0; - if (tab->bins != NULL) - initialize_bins(tab); - new_tab = tab; - new_entries = entries; + if (tab->bins != NULL) + initialize_bins(tab); + new_tab = tab; + 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); diff --git a/version.h b/version.h index b170660a54..7580b01561 100644 --- a/version.h +++ b/version.h @@ -11,11 +11,11 @@ https://github.com/ruby/ruby/blob/trunk/version.h#L11 # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR #define RUBY_VERSION_TEENY 3 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR -#define RUBY_PATCHLEVEL 73 +#define RUBY_PATCHLEVEL 74 #define RUBY_RELEASE_YEAR 2022 #define RUBY_RELEASE_MONTH 10 -#define RUBY_RELEASE_DAY 10 +#define RUBY_RELEASE_DAY 15 #include "ruby/version.h" -- cgit v1.2.1 -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/