diff --git a/io.c b/io.c index 24f141c..4b03a45 100644 --- a/io.c +++ b/io.c @@ -2281,7 +2281,10 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock) rb_sys_fail_path(fptr->pathv); } } - rb_str_set_len(str, n); + if (RSTRING_LEN(str) != n) { + rb_str_modify(str); + rb_str_set_len(str, n); + } if (n == 0) return Qnil; @@ -2602,7 +2605,10 @@ io_read(int argc, VALUE *argv, VALUE io) previous_mode = set_binary_mode_with_seek_cur(fptr); #endif n = io_fread(str, 0, len, fptr); - rb_str_set_len(str, n); + if (RSTRING_LEN(str) != n) { + rb_str_modify(str); + rb_str_set_len(str, n); + } #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) if (previous_mode == O_TEXT) { setmode(fptr->fd, O_TEXT); @@ -4390,7 +4396,10 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io) if (n == -1) { rb_sys_fail_path(fptr->pathv); } - rb_str_set_len(str, n); + if (RSTRING_LEN(str) != n) { + rb_str_modify(str); + rb_str_set_len(str, n); + } if (n == 0 && ilen > 0) { rb_eof_error(); } diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb index f165c64..91df2e6 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -2446,5 +2446,71 @@ End assert_raise(Errno::ESPIPE, Errno::EINVAL) { w.advise(:willneed) } end end + + def test_read_buffer_not_raise_shared_string_error + bug6764 = '[ruby-core:46586]' + size = 28 + t = Tempfile.new("test_io") + t.write("a" * size) + t.close + w = Tempfile.new("test_io") + assert_nothing_raised(RuntimeError, bug6764) do + File.open(t.path, "r") do |r| + buf = '' + while r.read(size, buf) + w << buf + end + end + end + ensure + t.close! + w.close! + end + + def test_sysread_buffer_not_raise_shared_string_error + bug6764 = '[ruby-core:46586]' + size = 28 + t = Tempfile.new("test_io") + t.write("a" * size) + t.close + w = Tempfile.new("test_io") + assert_nothing_raised(RuntimeError, bug6764) do + File.open(t.path, "r") do |r| + buf = '' + begin + while r.sysread(size, buf) + w << buf + end + rescue EOFError + end + end + end + ensure + t.close! + w.close! + end + + def test_readpartial_buffer_not_raise_shared_string_error + bug6764 = '[ruby-core:46586]' + size = 28 + t = Tempfile.new("test_io") + t.write("a" * size) + t.close + w = Tempfile.new("test_io") + assert_nothing_raised(RuntimeError, bug6764) do + File.open(t.path, "r") do |r| + buf = '' + begin + while r.readpartial(size, buf) + w << buf + end + rescue EOFError + end + end + end + ensure + t.close! + w.close! + end end