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

ruby-changes:59704

From: Jean <ko1@a...>
Date: Wed, 15 Jan 2020 10:39:05 +0900 (JST)
Subject: [ruby-changes:59704] 98ef38ada4 (master): Freeze Regexp literals

https://git.ruby-lang.org/ruby.git/commit/?id=98ef38ada4

From 98ef38ada43338c073f50a0093196f0356284625 Mon Sep 17 00:00:00 2001
From: Jean Boussier <jean.boussier@g...>
Date: Wed, 27 Nov 2019 11:40:18 +0000
Subject: Freeze Regexp literals

[Feature #8948] [Feature #16377]

Since Regexp literals always reference the same instance,
allowing to mutate them can lead to state leak.

diff --git a/re.c b/re.c
index 56b5144..3efd540 100644
--- a/re.c
+++ b/re.c
@@ -2967,6 +2967,7 @@ rb_reg_compile(VALUE str, int options, const char *sourcefile, int sourceline) https://github.com/ruby/ruby/blob/trunk/re.c#L2967
 	return Qnil;
     }
     FL_SET(re, REG_LITERAL);
+    rb_obj_freeze(re);
     return re;
 }
 
diff --git a/spec/ruby/core/marshal/dump_spec.rb b/spec/ruby/core/marshal/dump_spec.rb
index fc78ca4..ea02199 100644
--- a/spec/ruby/core/marshal/dump_spec.rb
+++ b/spec/ruby/core/marshal/dump_spec.rb
@@ -235,13 +235,13 @@ describe "Marshal.dump" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/marshal/dump_spec.rb#L235
     end
 
     it "dumps a Regexp with instance variables" do
-      o = //
+      o = Regexp.new("")
       o.instance_variable_set(:@ivar, :ivar)
       Marshal.dump(o).should == "\x04\bI/\x00\x00\a:\x06EF:\n@ivar:\tivar"
     end
 
     it "dumps an extended Regexp" do
-      Marshal.dump(//.extend(Meths)).should == "\x04\bIe:\nMeths/\x00\x00\x06:\x06EF"
+      Marshal.dump(Regexp.new("").extend(Meths)).should == "\x04\bIe:\nMeths/\x00\x00\x06:\x06EF"
     end
 
     it "dumps a Regexp subclass" do
diff --git a/spec/ruby/core/marshal/shared/load.rb b/spec/ruby/core/marshal/shared/load.rb
index 302d3d5..78fc9fb 100644
--- a/spec/ruby/core/marshal/shared/load.rb
+++ b/spec/ruby/core/marshal/shared/load.rb
@@ -623,7 +623,7 @@ describe :marshal_load, shared: true do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/marshal/shared/load.rb#L623
 
   describe "for a Regexp" do
     it "loads an extended Regexp" do
-      obj = /[a-z]/.extend(Meths, MethsMore)
+      obj = /[a-z]/.dup.extend(Meths, MethsMore)
       new_obj = Marshal.send(@method, "\004\be:\nMethse:\016MethsMore/\n[a-z]\000")
 
       new_obj.should == obj
diff --git a/spec/ruby/core/regexp/initialize_spec.rb b/spec/ruby/core/regexp/initialize_spec.rb
index 36fd5c7..ae188fb 100644
--- a/spec/ruby/core/regexp/initialize_spec.rb
+++ b/spec/ruby/core/regexp/initialize_spec.rb
@@ -5,8 +5,16 @@ describe "Regexp#initialize" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/regexp/initialize_spec.rb#L5
     Regexp.should have_private_method(:initialize)
   end
 
-  it "raises a SecurityError on a Regexp literal" do
-    -> { //.send(:initialize, "") }.should raise_error(SecurityError)
+  ruby_version_is ""..."2.7" do
+    it "raises a SecurityError on a Regexp literal" do
+      -> { //.send(:initialize, "") }.should raise_error(SecurityError)
+    end
+  end
+
+  ruby_version_is "2.7" do
+    it "raises a FrozenError on a Regexp literal" do
+      -> { //.send(:initialize, "") }.should raise_error(FrozenError)
+    end
   end
 
   it "raises a TypeError on an initialized non-literal Regexp" do
diff --git a/spec/ruby/core/string/match_spec.rb b/spec/ruby/core/string/match_spec.rb
index 78b94ba..5e988f3 100644
--- a/spec/ruby/core/string/match_spec.rb
+++ b/spec/ruby/core/string/match_spec.rb
@@ -137,7 +137,7 @@ describe "String#match" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/string/match_spec.rb#L137
   end
 
   it "calls match on the regular expression" do
-    regexp = /./
+    regexp = /./.dup
     regexp.should_receive(:match).and_return(:foo)
     'hello'.match(regexp).should == :foo
   end
diff --git a/spec/ruby/language/regexp_spec.rb b/spec/ruby/language/regexp_spec.rb
index 67c7c034..5881afe 100644
--- a/spec/ruby/language/regexp_spec.rb
+++ b/spec/ruby/language/regexp_spec.rb
@@ -18,6 +18,12 @@ describe "Literal Regexps" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/language/regexp_spec.rb#L18
     /Hello/.should be_kind_of(Regexp)
   end
 
+  ruby_version_is "2.7" do
+    it "is frozen" do
+      /Hello/.frozen?.should == true
+    end
+  end
+
   it "caches the Regexp object" do
     rs = []
     2.times do |i|
diff --git a/spec/ruby/optional/capi/encoding_spec.rb b/spec/ruby/optional/capi/encoding_spec.rb
index 857e421..b74a360 100644
--- a/spec/ruby/optional/capi/encoding_spec.rb
+++ b/spec/ruby/optional/capi/encoding_spec.rb
@@ -312,7 +312,7 @@ describe "C-API Encoding function" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/optional/capi/encoding_spec.rb#L312
     end
 
     it "sets the encoding of a Regexp to that of the second argument" do
-      @s.rb_enc_copy(/regexp/, @obj).encoding.should == Encoding::US_ASCII
+      @s.rb_enc_copy(/regexp/.dup, @obj).encoding.should == Encoding::US_ASCII
     end
   end
 
@@ -363,7 +363,7 @@ describe "C-API Encoding function" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/optional/capi/encoding_spec.rb#L363
     end
 
     it "sets the encoding of a Regexp to the encoding" do
-      @s.rb_enc_associate(/regexp/, "BINARY").encoding.should == Encoding::BINARY
+      @s.rb_enc_associate(/regexp/.dup, "BINARY").encoding.should == Encoding::BINARY
     end
 
     it "sets the encoding of a String to a default when the encoding is NULL" do
@@ -380,7 +380,7 @@ describe "C-API Encoding function" do https://github.com/ruby/ruby/blob/trunk/spec/ruby/optional/capi/encoding_spec.rb#L380
 
     it "sets the encoding of a Regexp to the encoding" do
       index = @s.rb_enc_find_index("UTF-8")
-      enc = @s.rb_enc_associate_index(/regexp/, index).encoding
+      enc = @s.rb_enc_associate_index(/regexp/.dup, index).encoding
       enc.should == Encoding::UTF_8
     end
 
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index a1d49c5..39577bd 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -622,7 +622,7 @@ class TestRegexp < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_regexp.rb#L622
 
   def test_dup
     assert_equal(//, //.dup)
-    assert_raise(TypeError) { //.instance_eval { initialize_copy(nil) } }
+    assert_raise(TypeError) { //.dup.instance_eval { initialize_copy(nil) } }
   end
 
   def test_regsub
-- 
cgit v0.10.2


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

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