diff --git a/ext/java/org/jruby/ext/stringio/StringIO.java b/ext/java/org/jruby/ext/stringio/StringIO.java index ce2e707..ed53fdd 100644 --- a/ext/java/org/jruby/ext/stringio/StringIO.java +++ b/ext/java/org/jruby/ext/stringio/StringIO.java @@ -1213,14 +1213,17 @@ private RubyString preadCommon(ThreadContext context, int argc, IRubyObject arg0 } case 2: len = RubyNumeric.fix2int(arg0); - offset = RubyNumeric.fix2int(arg1); if (!arg0.isNil()) { - len = RubyNumeric.fix2int(arg0); - if (len < 0) { throw runtime.newArgumentError("negative length " + len + " given"); } } + + offset = RubyNumeric.fix2int(arg1); + if (offset < 0) { + throw runtime.newErrnoEINVALError("pread: Invalid offset argument"); + } + break; default: throw runtime.newArgumentError(argc, 0, 2); @@ -1235,10 +1238,6 @@ private RubyString preadCommon(ThreadContext context, int argc, IRubyObject arg0 return (RubyString) str; } - if (offset < 0) { - throw runtime.newErrnoEINVALError("pread: Invalid offset argument"); - } - if (isOutside(offset)) { throw context.runtime.newEOFError(); } diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index bde80b7..cd29875 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -161,6 +161,16 @@ strio_substr(struct StringIO *ptr, long pos, long len, rb_encoding *enc) return enc_subseq(str, pos, len, enc); } +static VALUE +strio_readbuf(struct StringIO *ptr, VALUE str) +{ + if (!NIL_P(str)) { + StringValue(str); + rb_str_modify(str); + } + return str; +} + #define StringIO(obj) get_strio(obj) #define StringIOForRead(obj) get_strio_for_read(obj) @@ -1684,11 +1694,7 @@ strio_read(int argc, VALUE *argv, VALUE self) switch (argc) { case 2: - str = argv[1]; - if (!NIL_P(str)) { - StringValue(str); - rb_str_modify(str); - } + str = strio_readbuf(ptr, argv[1]); /* fall through */ case 1: if (!NIL_P(argv[0])) { @@ -1753,6 +1759,8 @@ static VALUE strio_pread(int argc, VALUE *argv, VALUE self) { VALUE rb_len, rb_offset, rb_buf; + struct StringIO *ptr = readable(self); + rb_scan_args(argc, argv, "21", &rb_len, &rb_offset, &rb_buf); long len = NUM2LONG(rb_len); long offset = NUM2LONG(rb_offset); @@ -1761,6 +1769,12 @@ strio_pread(int argc, VALUE *argv, VALUE self) rb_raise(rb_eArgError, "negative string size (or size too big): %" PRIsVALUE, rb_len); } + if (offset < 0) { + rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset)); + } + + rb_buf = strio_readbuf(ptr, rb_buf); + if (len == 0) { if (NIL_P(rb_buf)) { return rb_str_new("", 0); @@ -1768,12 +1782,6 @@ strio_pread(int argc, VALUE *argv, VALUE self) return rb_buf; } - if (offset < 0) { - rb_syserr_fail_str(EINVAL, rb_sprintf("pread: Invalid offset argument: %" PRIsVALUE, rb_offset)); - } - - struct StringIO *ptr = readable(self); - if (outside_p(ptr, offset)) { rb_eof_error(); } diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb index 656c0bb..aca250a 100644 --- a/test/stringio/test_stringio.rb +++ b/test/stringio/test_stringio.rb @@ -831,9 +831,11 @@ def test_pread assert_raise(EOFError) { f.pread(1, 5) } assert_raise(ArgumentError) { f.pread(-1, 0) } assert_raise(Errno::EINVAL) { f.pread(3, -1) } + assert_raise(Errno::EINVAL) { f.pread(0, -1) } + assert_raise(IOError) { StringIO.new(nil, "w").pread(3, 0) } + assert_raise(TypeError) { f.pread(3, 0, []) } assert_equal "".b, StringIO.new("").pread(0, 0) - assert_equal "".b, StringIO.new("").pread(0, -10) buf = "stale".b assert_equal "stale".b, StringIO.new("").pread(0, 0, buf)