summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--io.c15
-rw-r--r--test/ruby/test_io.rb49
3 files changed, 69 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 5aed647b40..8ef472344d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/io.c b/io.c
index 24f141c825..e007512135 100644
--- a/io.c
+++ b/io.c
@@ -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