mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	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(+)
This commit is contained in:
		
							parent
							
								
									86f7e55dfb
								
							
						
					
					
						commit
						44b87adc07
					
				
					 5 changed files with 92 additions and 1 deletions
				
			
		
							
								
								
									
										1
									
								
								array.c
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								array.c
									
										
									
									
									
								
							| 
						 | 
					@ -3838,6 +3838,7 @@ select_bang_ensure(VALUE a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (i2 < len && i2 < i1) {
 | 
					    if (i2 < len && i2 < i1) {
 | 
				
			||||||
	long tail = 0;
 | 
						long tail = 0;
 | 
				
			||||||
 | 
					        rb_ary_modify(ary);
 | 
				
			||||||
	if (i1 < len) {
 | 
						if (i1 < len) {
 | 
				
			||||||
	    tail = len - i1;
 | 
						    tail = len - i1;
 | 
				
			||||||
            RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
 | 
					            RARRAY_PTR_USE_TRANSIENT(ary, ptr, {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								hash.c
									
										
									
									
									
								
							
							
						
						
									
										3
									
								
								hash.c
									
										
									
									
									
								
							| 
						 | 
					@ -2476,6 +2476,7 @@ static int
 | 
				
			||||||
delete_if_i(VALUE key, VALUE value, VALUE hash)
 | 
					delete_if_i(VALUE key, VALUE value, VALUE hash)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (RTEST(rb_yield_values(2, key, value))) {
 | 
					    if (RTEST(rb_yield_values(2, key, value))) {
 | 
				
			||||||
 | 
						rb_hash_modify(hash);
 | 
				
			||||||
	return ST_DELETE;
 | 
						return ST_DELETE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return ST_CONTINUE;
 | 
					    return ST_CONTINUE;
 | 
				
			||||||
| 
						 | 
					@ -2753,6 +2754,7 @@ static int
 | 
				
			||||||
keep_if_i(VALUE key, VALUE value, VALUE hash)
 | 
					keep_if_i(VALUE key, VALUE value, VALUE hash)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!RTEST(rb_yield_values(2, key, value))) {
 | 
					    if (!RTEST(rb_yield_values(2, key, value))) {
 | 
				
			||||||
 | 
						rb_hash_modify(hash);
 | 
				
			||||||
	return ST_DELETE;
 | 
						return ST_DELETE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return ST_CONTINUE;
 | 
					    return ST_CONTINUE;
 | 
				
			||||||
| 
						 | 
					@ -3322,6 +3324,7 @@ transform_values_foreach_replace(st_data_t *key, st_data_t *value, st_data_t arg
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    VALUE new_value = rb_yield((VALUE)*value);
 | 
					    VALUE new_value = rb_yield((VALUE)*value);
 | 
				
			||||||
    VALUE hash = (VALUE)argp;
 | 
					    VALUE hash = (VALUE)argp;
 | 
				
			||||||
 | 
					    rb_hash_modify(hash);
 | 
				
			||||||
    RB_OBJ_WRITE(hash, value, new_value);
 | 
					    RB_OBJ_WRITE(hash, value, new_value);
 | 
				
			||||||
    return ST_CONTINUE;
 | 
					    return ST_CONTINUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -754,6 +754,15 @@ class TestArray < Test::Unit::TestCase
 | 
				
			||||||
    a = @cls[ 5, 6, 7, 8, 9, 10 ]
 | 
					    a = @cls[ 5, 6, 7, 8, 9, 10 ]
 | 
				
			||||||
    assert_equal(9, a.delete_if {|i| break i if i > 8; i < 7})
 | 
					    assert_equal(9, a.delete_if {|i| break i if i > 8; i < 7})
 | 
				
			||||||
    assert_equal(@cls[7, 8, 9, 10], a, bug2545)
 | 
					    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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def test_dup
 | 
					  def test_dup
 | 
				
			||||||
| 
						 | 
					@ -1322,6 +1331,15 @@ class TestArray < Test::Unit::TestCase
 | 
				
			||||||
    a = @cls[ 5, 6, 7, 8, 9, 10 ]
 | 
					    a = @cls[ 5, 6, 7, 8, 9, 10 ]
 | 
				
			||||||
    assert_equal(9, a.reject! {|i| break i if i > 8; i < 7})
 | 
					    assert_equal(9, a.reject! {|i| break i if i > 8; i < 7})
 | 
				
			||||||
    assert_equal(@cls[7, 8, 9, 10], a, bug2545)
 | 
					    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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def test_shared_array_reject!
 | 
					  def test_shared_array_reject!
 | 
				
			||||||
| 
						 | 
					@ -2599,6 +2617,15 @@ class TestArray < Test::Unit::TestCase
 | 
				
			||||||
    a = @cls[ 1, 2, 3, 4, 5 ]
 | 
					    a = @cls[ 1, 2, 3, 4, 5 ]
 | 
				
			||||||
    a.select! {|i| a.clear if i == 5; false }
 | 
					    a.select! {|i| a.clear if i == 5; false }
 | 
				
			||||||
    assert_equal(0, a.size, bug13053)
 | 
					    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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # also select!
 | 
					  # also select!
 | 
				
			||||||
| 
						 | 
					@ -2614,6 +2641,15 @@ class TestArray < Test::Unit::TestCase
 | 
				
			||||||
    a = @cls[ 1, 2, 3, 4, 5 ]
 | 
					    a = @cls[ 1, 2, 3, 4, 5 ]
 | 
				
			||||||
    assert_equal(a, a.keep_if { |i| i > 3 })
 | 
					    assert_equal(a, a.keep_if { |i| i > 3 })
 | 
				
			||||||
    assert_equal(@cls[4, 5], a)
 | 
					    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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def test_filter
 | 
					  def test_filter
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -419,6 +419,15 @@ class TestHash < Test::Unit::TestCase
 | 
				
			||||||
      true
 | 
					      true
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    assert_equal(base.size, n)
 | 
					    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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def test_keep_if
 | 
					  def test_keep_if
 | 
				
			||||||
| 
						 | 
					@ -426,6 +435,14 @@ class TestHash < Test::Unit::TestCase
 | 
				
			||||||
    assert_equal({3=>4,5=>6}, h.keep_if {|k, v| k + v >= 7 })
 | 
					    assert_equal({3=>4,5=>6}, h.keep_if {|k, v| k + v >= 7 })
 | 
				
			||||||
    h = @cls[1=>2,3=>4,5=>6]
 | 
					    h = @cls[1=>2,3=>4,5=>6]
 | 
				
			||||||
    assert_equal({1=>2,3=>4,5=>6}, h.keep_if{true})
 | 
					    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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def test_compact
 | 
					  def test_compact
 | 
				
			||||||
| 
						 | 
					@ -722,6 +739,15 @@ class TestHash < Test::Unit::TestCase
 | 
				
			||||||
    h = base.dup
 | 
					    h = base.dup
 | 
				
			||||||
    assert_equal(h3, h.reject! {|k,v| v })
 | 
					    assert_equal(h3, h.reject! {|k,v| v })
 | 
				
			||||||
    assert_equal(h3, h)
 | 
					    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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def test_replace
 | 
					  def test_replace
 | 
				
			||||||
| 
						 | 
					@ -1025,6 +1051,14 @@ class TestHash < Test::Unit::TestCase
 | 
				
			||||||
    assert_equal({3=>4,5=>6}, h)
 | 
					    assert_equal({3=>4,5=>6}, h)
 | 
				
			||||||
    h = @cls[1=>2,3=>4,5=>6]
 | 
					    h = @cls[1=>2,3=>4,5=>6]
 | 
				
			||||||
    assert_equal(nil, h.select!{true})
 | 
					    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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def test_slice
 | 
					  def test_slice
 | 
				
			||||||
| 
						 | 
					@ -1077,6 +1111,14 @@ class TestHash < Test::Unit::TestCase
 | 
				
			||||||
    assert_equal({3=>4,5=>6}, h)
 | 
					    assert_equal({3=>4,5=>6}, h)
 | 
				
			||||||
    h = @cls[1=>2,3=>4,5=>6]
 | 
					    h = @cls[1=>2,3=>4,5=>6]
 | 
				
			||||||
    assert_equal(nil, h.filter!{true})
 | 
					    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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def test_clear2
 | 
					  def test_clear2
 | 
				
			||||||
| 
						 | 
					@ -1720,6 +1762,15 @@ class TestHash < Test::Unit::TestCase
 | 
				
			||||||
    x = @cls[a: 1, b: 2, c: 3]
 | 
					    x = @cls[a: 1, b: 2, c: 3]
 | 
				
			||||||
    y = x.transform_values!.with_index {|v, i| "#{v}.#{i}" }
 | 
					    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))
 | 
					    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
 | 
					  end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  def test_broken_hash_value
 | 
					  def test_broken_hash_value
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@
 | 
				
			||||||
# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
 | 
					# define RUBY_VERSION_MINOR RUBY_API_VERSION_MINOR
 | 
				
			||||||
#define RUBY_VERSION_TEENY 2
 | 
					#define RUBY_VERSION_TEENY 2
 | 
				
			||||||
#define RUBY_RELEASE_DATE RUBY_RELEASE_YEAR_STR"-"RUBY_RELEASE_MONTH_STR"-"RUBY_RELEASE_DAY_STR
 | 
					#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_YEAR 2021
 | 
				
			||||||
#define RUBY_RELEASE_MONTH 5
 | 
					#define RUBY_RELEASE_MONTH 5
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue