summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKoichi Sasada <[email protected]>2021-12-17 14:22:14 +0900
committerKoichi Sasada <[email protected]>2021-12-17 15:46:50 +0900
commit37bd795cf8bc9681fccaf9b2d42292b14610a310 (patch)
tree9fcf88eb81175594565290442d6292b4ad0cb527
parentd524b9dec9859ce307f6f913be46144557e8edbd (diff)
`ENV` ivars should not be accessible from ractors
The `ENV` object can have instance variables like other objects, but they should be accessed only on the main ractor. fix https://github.com/ruby/ruby/pull/5263#issuecomment-995585766
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5288
-rw-r--r--hash.c13
-rw-r--r--test/ruby/test_env.rb30
2 files changed, 42 insertions, 1 deletions
diff --git a/hash.c b/hash.c
index deb5e77872..da9af425c1 100644
--- a/hash.c
+++ b/hash.c
@@ -6653,6 +6653,17 @@ env_dup(VALUE obj)
rb_raise(rb_eTypeError, "Cannot dup ENV, use ENV.to_h to get a copy of ENV as a hash");
}
+const rb_data_type_t env_data_type = {
+ "ENV",
+ {
+ NULL,
+ RUBY_DEFAULT_FREE,
+ NULL,
+ NULL,
+ },
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
+};
+
/*
* A \Hash maps each of its unique keys to a specific value.
*
@@ -7308,7 +7319,7 @@ Init_Hash(void)
* envtbl = rb_define_class("ENV", rb_cObject);
*/
origenviron = environ;
- envtbl = rb_obj_alloc(rb_cObject);
+ envtbl = TypedData_Wrap_Struct(rb_cObject, &env_data_type, NULL);
rb_extend_object(envtbl, rb_mEnumerable);
FL_SET_RAW(envtbl, RUBY_FL_SHAREABLE);
diff --git a/test/ruby/test_env.rb b/test/ruby/test_env.rb
index 442fc60f7e..87ccd5102b 100644
--- a/test/ruby/test_env.rb
+++ b/test/ruby/test_env.rb
@@ -1434,6 +1434,36 @@ class TestEnv < Test::Unit::TestCase
end;
end
+ def test_ivar_in_env_should_not_be_access_from_non_main_ractors
+ assert_ractor <<~RUBY
+ ENV.instance_eval{ @a = "hello" }
+ assert_equal "hello", ENV.instance_variable_get(:@a)
+
+ r_get = Ractor.new do
+ ENV.instance_variable_get(:@a)
+ rescue Ractor::IsolationError => e
+ e
+ end
+ assert_equal Ractor::IsolationError, r_get.take.class
+
+ r_get = Ractor.new do
+ ENV.instance_eval{ @a }
+ rescue Ractor::IsolationError => e
+ e
+ end
+
+ assert_equal Ractor::IsolationError, r_get.take.class
+
+ r_set = Ractor.new do
+ ENV.instance_eval{ @b = "hello" }
+ rescue Ractor::IsolationError => e
+ e
+ end
+
+ assert_equal Ractor::IsolationError, r_set.take.class
+ RUBY
+ end
+
if RUBY_PLATFORM =~ /bccwin|mswin|mingw/
def test_memory_leak_aset
bug9977 = '[ruby-dev:48323] [Bug #9977]'