diff options
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | io.c | 15 | ||||
-rw-r--r-- | test/ruby/test_io.rb | 49 |
3 files changed, 69 insertions, 3 deletions
@@ -1,3 +1,11 @@ +Sun Sep 16 11:39:12 2012 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * io.c (io_set_read_length): if the read length equals to the buffer + string size then nothing to do. or ensure the string modifiable + before setting the length only when the former is shorter. based on + the patch in [ruby-core:47541] by Hiroshi Shirosaki. + [ruby-core:46586] [Bug #6764] + Sun Sep 16 08:57:52 2012 Nobuyoshi Nakada <nobu@ruby-lang.org> * configure.in (strict_warnflags): separate strict flags from @@ -2158,6 +2158,15 @@ io_setstrbuf(VALUE *str, long len) rb_str_modify_expand(*str, len); } +static void +io_set_read_length(VALUE str, long n) +{ + if (RSTRING_LEN(str) != n) { + rb_str_modify(str); + rb_str_set_len(str, n); + } +} + static VALUE read_all(rb_io_t *fptr, long siz, VALUE str) { @@ -2281,7 +2290,7 @@ io_getpartial(int argc, VALUE *argv, VALUE io, int nonblock) rb_sys_fail_path(fptr->pathv); } } - rb_str_set_len(str, n); + io_set_read_length(str, n); if (n == 0) return Qnil; @@ -2602,7 +2611,7 @@ 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); + io_set_read_length(str, n); #if defined(RUBY_TEST_CRLF_ENVIRONMENT) || defined(_WIN32) if (previous_mode == O_TEXT) { setmode(fptr->fd, O_TEXT); @@ -4390,7 +4399,7 @@ rb_io_sysread(int argc, VALUE *argv, VALUE io) if (n == -1) { rb_sys_fail_path(fptr->pathv); } - rb_str_set_len(str, n); + io_set_read_length(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 f165c640b1..e266f115ba 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -2446,5 +2446,54 @@ End assert_raise(Errno::ESPIPE, Errno::EINVAL) { w.advise(:willneed) } end end + + def assert_buffer_not_raise_shared_string_error + bug6764 = '[ruby-core:46586]' + size = 28 + data = [*"a".."z", *"A".."Z"].shuffle.join("") + t = Tempfile.new("test_io") + t.write(data) + t.close + w = Tempfile.new("test_io") + assert_nothing_raised(RuntimeError, bug6764) do + File.open(t.path, "r") do |r| + buf = '' + while yield(r, size, buf) + w << buf + end + end + end + w.close + assert_equal(data, w.open.read, bug6764) + ensure + t.close! + w.close! + end + + def test_read_buffer_not_raise_shared_string_error + assert_buffer_not_raise_shared_string_error do |r, size, buf| + r.read(size, buf) + end + end + + def test_sysread_buffer_not_raise_shared_string_error + assert_buffer_not_raise_shared_string_error do |r, size, buf| + begin + r.sysread(size, buf) + rescue EOFError + nil + end + end + end + + def test_readpartial_buffer_not_raise_shared_string_error + assert_buffer_not_raise_shared_string_error do |r, size, buf| + begin + r.readpartial(size, buf) + rescue EOFError + nil + end + end + end end |