diff options
author | Kasumi Hanazuki <[email protected]> | 2024-11-07 05:55:39 +0900 |
---|---|---|
committer | GitHub <[email protected]> | 2024-11-06 20:55:39 +0000 |
commit | 35bf6603372360c7680653328274a670fa1d9f38 (patch) | |
tree | f6982777da87e3f404b8d45478e80bef97dba3cf /test/ruby/test_io_buffer.rb | |
parent | 56ecc243e230e8e99761ec0ffc5116601f094bb0 (diff) |
io_buffer.c: Allow copies between overlapping buffers with #copy and #set_string (#11640)
The current implementation of `IO::Buffer#copy` and `#set_string` has
an undefined behavior when the source and destination memory overlaps,
due to the underlying use of the `memcpy` C function.
This patch guarantees the methods to be safe even when copying between
overlapping buffers by replacing `memcpy` with `memmove`,
Fixes: [Bug #20745]
Notes
Notes:
Merged-By: ioquatix <[email protected]>
Diffstat (limited to 'test/ruby/test_io_buffer.rb')
-rw-r--r-- | test/ruby/test_io_buffer.rb | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/test/ruby/test_io_buffer.rb b/test/ruby/test_io_buffer.rb index 178ed05003..55296c1f23 100644 --- a/test/ruby/test_io_buffer.rb +++ b/test/ruby/test_io_buffer.rb @@ -633,4 +633,54 @@ class TestIOBuffer < Test::Unit::TestCase end end end + + def test_copy_overlapped_fwd + buf = IO::Buffer.for('0123456789').dup + buf.copy(buf, 3, 7) + assert_equal '0120123456', buf.get_string + end + + def test_copy_overlapped_bwd + buf = IO::Buffer.for('0123456789').dup + buf.copy(buf, 0, 7, 3) + assert_equal '3456789789', buf.get_string + end + + def test_copy_null_destination + buf = IO::Buffer.new(0) + assert_predicate buf, :null? + buf.copy(IO::Buffer.for('a'), 0, 0) + assert_predicate buf, :empty? + end + + def test_copy_null_source + buf = IO::Buffer.for('a').dup + src = IO::Buffer.new(0) + assert_predicate src, :null? + buf.copy(src, 0, 0) + assert_equal 'a', buf.get_string + end + + def test_set_string_overlapped_fwd + str = +'0123456789' + IO::Buffer.for(str) do |buf| + buf.set_string(str, 3, 7) + end + assert_equal '0120123456', str + end + + def test_set_string_overlapped_bwd + str = +'0123456789' + IO::Buffer.for(str) do |buf| + buf.set_string(str, 0, 7, 3) + end + assert_equal '3456789789', str + end + + def test_set_string_null_destination + buf = IO::Buffer.new(0) + assert_predicate buf, :null? + buf.set_string('a', 0, 0) + assert_predicate buf, :empty? + end end |