Skip to content

Commit c479492

Browse files
fresh-eggsnobu
authored andcommitted
Resize ary when Array#sort! block modifies embedded ary
In cases where `rb_ary_sort_bang` is called with a block and tmp is an embedded array, we need to account for the block potentially impacting the capacity of ary. ex: ``` var_0 = (1..70).to_a var_0.sort! do |var_0_block_129, var_1_block_129| var_0.pop var_1_block_129 <=> var_0_block_129 end.shift(3) ``` The above example can put the array into a corrupted state resulting in a heap buffer overflow and possible segfault: ``` ERROR: AddressSanitizer: heap-buffer-overflow on address [...] WRITE of size 560 at 0x60b0000034f0 thread T0 [...] ``` This commit adds a conditional to determine when the capacity of ary has been modified by the provided block. If this is the case, ensure that the capacity of ary is adjusted to handle at minimum the len of tmp.
1 parent 43a6690 commit c479492

File tree

2 files changed

+12
-0
lines changed

2 files changed

+12
-0
lines changed

array.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3393,6 +3393,9 @@ rb_ary_sort_bang(VALUE ary)
33933393
rb_ary_unshare(ary);
33943394
FL_SET_EMBED(ary);
33953395
}
3396+
if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
3397+
ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
3398+
}
33963399
ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
33973400
ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
33983401
}

test/ruby/test_array.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3556,6 +3556,15 @@ def test_big_array_literal_with_kwsplat
35563556
assert_equal(10000, eval(lit).size)
35573557
end
35583558

3559+
def test_array_safely_modified_by_sort_block
3560+
var_0 = (1..70).to_a
3561+
var_0.sort! do |var_0_block_129, var_1_block_129|
3562+
var_0.pop
3563+
var_1_block_129 <=> var_0_block_129
3564+
end.shift(3)
3565+
assert_equal((1..67).to_a.reverse, var_0)
3566+
end
3567+
35593568
private
35603569
def need_continuation
35613570
unless respond_to?(:callcc, true)

0 commit comments

Comments
 (0)