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

ruby-changes:66309

From: nagachika <ko1@a...>
Date: Sun, 23 May 2021 16:09:46 +0900 (JST)
Subject: [ruby-changes:66309] 44b87adc07 (ruby_3_0): merge revision(s) e019dd24df4ed7063ad80d4c2e4070141793f598,7954bb056be30e86c419fe3792064d28990a4999,7d3fdfb27dac456827b004d9e66a44b15f8cd762: [Backport #17736]

https://git.ruby-lang.org/ruby.git/commit/?id=44b87adc07

From 44b87adc07621b6a8eddfcf4aaff34ce634179d4 Mon Sep 17 00:00:00 2001
From: nagachika <nagachika@r...>
Date: Sun, 23 May 2021 15:51:10 +0900
Subject: merge revision(s)
 e019dd24df4ed7063ad80d4c2e4070141793f598,7954bb056be30e86c419fe3792064d28990a4999,7d3fdfb27dac456827b004d9e66a44b15f8cd762:
 [Backport #17736]

	Ensure the receiver is modifiable before shrinking [Bug #17736]

	* Ensure the receiver is modifiable before shinking [Bug #17736]

	* Assert the receivers are not modified
	---
	 array.c                 |  1 +
	 test/ruby/test_array.rb | 36 ++++++++++++++++++++++++++++++++++++
	 2 files changed, 37 insertions(+)

	Some Hash destructive methods ensure the receiver modifiable [Bug
	 #17736]

	refs:

	* https://bugs.ruby-lang.org/issues/17736
	* https://github.com/ruby/ruby/pull/4296

	This commit aims to cover following methods

	* Hash#select!
	* Hash#filter!
	* Hash#keep_if
	* Hash#reject!
	* Hash#delete_if

	I think these are not all.

	---

	* Ensure the receiver is modifiable or not
	* Assert the receiver is not modified
	---
	 hash.c                 |  2 ++
	 test/ruby/test_hash.rb | 42 ++++++++++++++++++++++++++++++++++++++++++
	 2 files changed, 44 insertions(+)

	Hash#transform_values! ensures receiver modifiable in block [Bug
	 #17736]

	---
	 hash.c                 | 1 +
	 test/ruby/test_hash.rb | 9 +++++++++
	 2 files changed, 10 insertions(+)
---
 array.c                 |  1 +
 hash.c                  |  3 +++
 test/ruby/test_array.rb | 36 ++++++++++++++++++++++++++++++++++
 test/ruby/test_hash.rb  | 51 +++++++++++++++++++++++++++++++++++++++++++++++++
 version.h               |  2 +-
 5 files changed, 92 insertions(+), 1 deletion(-)

diff --git a/array.c b/array.c
index ea84473..c0c8016 100644
--- a/array.c
+++ b/array.c
@@ -3838,6 +3838,7 @@ select_bang_ensure(VALUE a) https://github.com/ruby/ruby/blob/trunk/array.c#L3838
 
     if (i2 < len && i2 < i1) {
 	long tail = 0;
+        rb_ary_modify(ary);
 	if (i1 < len) {
 	    tail = len - i1;
             RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
diff --git a/hash.c b/hash.c
index e29e985..b79f4f8 100644
--- a/hash.c
+++ b/hash.c
@@ -2476,6 +2476,7 @@ static int https://github.com/ruby/ruby/blob/trunk/hash.c#L2476
 delete_if_i(VALUE key, VALUE value, VALUE hash)
 {
     if (RTEST(rb_yield_values(2, key, value))) {
+	rb_hash_modify(hash);
 	return ST_DELETE;
     }
     return ST_CONTINUE;
@@ -2753,6 +2754,7 @@ static int https://github.com/ruby/ruby/blob/trunk/hash.c#L2754
 keep_if_i(VALUE key, VALUE value, VALUE hash)
 {
     if (!RTEST(rb_yield_values(2, key, value))) {
+	rb_hash_modify(hash);
 	return ST_DELETE;
     }
     return ST_CONTINUE;
@@ -3322,6 +3324,7 @@ transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t arg https://github.com/ruby/ruby/blob/trunk/hash.c#L3324
 {
     VALUE new_value = rb_yield((VALUE)*value);
     VALUE hash = (VALUE)argp;
+    rb_hash_modify(hash);
     RB_OBJ_WRITE(hash, value, new_value);
     return ST_CONTINUE;
 }
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 522b58e..789531f 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -754,6 +754,15 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L754
     a = @cls[ 5, 6, 7, 8, 9, 10 ]
     assert_equal(9, a.delete_if {|i| break i if i > 8; i < 7})
     assert_equal(@cls[7, 8, 9, 10], a, bug2545)
+
+    assert_raise(FrozenError) do
+      a = @cls[1, 2, 3, 42]
+      a.delete_if do
+        a.freeze
+        true
+      end
+    end
+    assert_equal(@cls[1, 2, 3, 42], a)
   end
 
   def test_dup
@@ -1322,6 +1331,15 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L1331
     a = @cls[ 5, 6, 7, 8, 9, 10 ]
     assert_equal(9, a.reject! {|i| break i if i > 8; i < 7})
     assert_equal(@cls[7, 8, 9, 10], a, bug2545)
+
+    assert_raise(FrozenError) do
+      a = @cls[1, 2, 3, 42]
+      a.reject! do
+        a.freeze
+        true
+      end
+    end
+    assert_equal(@cls[1, 2, 3, 42], a)
   end
 
   def test_shared_array_reject!
@@ -2599,6 +2617,15 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L2617
     a = @cls[ 1, 2, 3, 4, 5 ]
     a.select! {|i| a.clear if i == 5; false }
     assert_equal(0, a.size, bug13053)
+
+    assert_raise(FrozenError) do
+      a = @cls[1, 2, 3, 42]
+      a.select! do
+        a.freeze
+        false
+      end
+    end
+    assert_equal(@cls[1, 2, 3, 42], a)
   end
 
   # also select!
@@ -2614,6 +2641,15 @@ class TestArray < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_array.rb#L2641
     a = @cls[ 1, 2, 3, 4, 5 ]
     assert_equal(a, a.keep_if { |i| i > 3 })
     assert_equal(@cls[4, 5], a)
+
+    assert_raise(FrozenError) do
+      a = @cls[1, 2, 3, 42]
+      a.keep_if do
+        a.freeze
+        false
+      end
+    end
+    assert_equal(@cls[1, 2, 3, 42], a)
   end
 
   def test_filter
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index 812b9e6..aaf92d4 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -419,6 +419,15 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L419
       true
     }
     assert_equal(base.size, n)
+
+    h = base.dup
+    assert_raise(FrozenError) do
+      h.delete_if do
+        h.freeze
+        true
+      end
+    end
+    assert_equal(base.dup, h)
   end
 
   def test_keep_if
@@ -426,6 +435,14 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L435
     assert_equal({3=>4,5=>6}, h.keep_if {|k, v| k + v >= 7 })
     h = @cls[1=>2,3=>4,5=>6]
     assert_equal({1=>2,3=>4,5=>6}, h.keep_if{true})
+    h = @cls[1=>2,3=>4,5=>6]
+    assert_raise(FrozenError) do
+      h.keep_if do
+        h.freeze
+        false
+      end
+    end
+    assert_equal(@cls[1=>2,3=>4,5=>6], h)
   end
 
   def test_compact
@@ -722,6 +739,15 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L739
     h = base.dup
     assert_equal(h3, h.reject! {|k,v| v })
     assert_equal(h3, h)
+
+    h = base.dup
+    assert_raise(FrozenError) do
+      h.reject! do
+        h.freeze
+        true
+      end
+    end
+    assert_equal(base.dup, h)
   end
 
   def test_replace
@@ -1025,6 +1051,14 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L1051
     assert_equal({3=>4,5=>6}, h)
     h = @cls[1=>2,3=>4,5=>6]
     assert_equal(nil, h.select!{true})
+    h = @cls[1=>2,3=>4,5=>6]
+    assert_raise(FrozenError) do
+      h.select! do
+        h.freeze
+        false
+      end
+    end
+    assert_equal(@cls[1=>2,3=>4,5=>6], h)
   end
 
   def test_slice
@@ -1077,6 +1111,14 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L1111
     assert_equal({3=>4,5=>6}, h)
     h = @cls[1=>2,3=>4,5=>6]
     assert_equal(nil, h.filter!{true})
+    h = @cls[1=>2,3=>4,5=>6]
+    assert_raise(FrozenError) do
+      h.filter! do
+        h.freeze
+        false
+      end
+    end
+    assert_equal(@cls[1=>2,3=>4,5=>6], h)
   end
 
   def test_clear2
@@ -1720,6 +1762,15 @@ class TestHash < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_hash.rb#L1762
     x = @cls[a: 1, b: 2, c: 3]
     y = x.transform_values!.with_index {|v, i| "#{v}.#{i}" }
     assert_equal(%w(1.0  2.1  3.2), y.values_at(:a, :b, :c))
+
+    x = @cls[a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10]
+    assert_raise(FrozenError) do
+      x.transform_values!() do |v|
+        x.freeze if v == 2
+        v.succ
+      end
+    end
+    assert_equal(@cls[a: 2, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10], x)
   end
 
   def test_broken_hash_value
diff --git a/version.h b/version.h
index 36d0caa..de064cc 100644
--- a/version.h
+++ b/version.h
@@ -12,7 +12,7 @@ https://github.com/ruby/ruby/blob/trunk/version.h#L12
 # define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
 #define RUBY_VERSION_TEENY 2
 #define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
-#define RUBY_PATCHLEVEL 86
+#define RUBY_PATCHLEVEL 87
 
 #define RUBY_RELEASE_YEAR 2021
 #define RUBY_RELEASE_MONTH 5
-- 
cgit v1.1


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

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