From 4ed1d6b7cf06c8dad60b698066ecae52c482789a Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 7 May 2026 14:31:30 +0900 Subject: [PATCH] Cannot read into the underlying string Fix https://hackerone.com/reports/3716987 --- ext/java/org/jruby/ext/stringio/StringIO.java | 18 +++++++++++------- ext/stringio/stringio.c | 3 +++ test/stringio/test_stringio.rb | 3 +++ 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/ext/java/org/jruby/ext/stringio/StringIO.java b/ext/java/org/jruby/ext/stringio/StringIO.java index acbb5db..e84fa17 100644 --- a/ext/java/org/jruby/ext/stringio/StringIO.java +++ b/ext/java/org/jruby/ext/stringio/StringIO.java @@ -1110,7 +1110,7 @@ private IRubyObject readCommon(ThreadContext context, int argc, IRubyObject arg0 final RubyString string; switch (argc) { case 2: - str = readBuf(arg1); + str = readBuf(context, ptr, arg1); case 1: if (!arg0.isNil()) { len = RubyNumeric.fix2int(arg0); @@ -1202,7 +1202,7 @@ private RubyString preadCommon(ThreadContext context, int argc, IRubyObject arg0 switch (argc) { case 3: - str = readBuf(arg2); + str = readBuf(context, ptr, arg2); case 2: len = RubyNumeric.fix2int(arg0); if (!arg0.isNil()) { @@ -1694,12 +1694,16 @@ private static IRubyObject substrString(RubyString ch, IRubyObject str, Ruby run return str; } - private static IRubyObject readBuf(IRubyObject str) { - if (!str.isNil()) { - str = str.convertToString(); - modifyString((RubyString) str); + private static IRubyObject readBuf(ThreadContext context, StringIOData ptr, IRubyObject arg) { + if (!arg.isNil()) { + arg = arg.convertToString(); + RubyString str = (RubyString) arg; + modifyString(str); + if (str == ptr.string) { + throw context.runtime.newArgumentError("cannot read into the underlying string"); + } } - return str; + return arg; } // MRI: strio_write diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index cd29875..d863dcc 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -167,6 +167,9 @@ strio_readbuf(struct StringIO *ptr, VALUE str) if (!NIL_P(str)) { StringValue(str); rb_str_modify(str); + if (str == ptr->string) { + rb_raise(rb_eArgError, "cannot read into the underlying string"); + } } return str; } diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb index aca250a..0f61245 100644 --- a/test/stringio/test_stringio.rb +++ b/test/stringio/test_stringio.rb @@ -765,6 +765,8 @@ def test_read s = "" f.read(nil, s) assert_equal(Encoding::ASCII_8BIT, s.encoding, bug20418) + + assert_raise(ArgumentError) {f.read(1, f.string)} end def test_readpartial @@ -830,6 +832,7 @@ def test_pread assert_raise(EOFError) { f.pread(1, 5) } assert_raise(ArgumentError) { f.pread(-1, 0) } + assert_raise(ArgumentError) { f.pread(0, 0, f.string) } 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) }