From 7a953f4a0ab7a5147cd817f1d2730447769b5c72 Mon Sep 17 00:00:00 2001 From: koh-sh <34917718+koh-sh@users.noreply.github.com> Date: Sat, 9 Aug 2025 12:13:52 +0900 Subject: [PATCH 1/2] fix: prevent segfault in StringIO#seek with SEEK_END on null device --- ext/stringio/stringio.c | 6 +++++- test/stringio/test_stringio.rb | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ext/stringio/stringio.c b/ext/stringio/stringio.c index 45899bd9..17ef3fc6 100644 --- a/ext/stringio/stringio.c +++ b/ext/stringio/stringio.c @@ -837,7 +837,11 @@ strio_seek(int argc, VALUE *argv, VALUE self) offset = ptr->pos; break; case 2: - offset = RSTRING_LEN(ptr->string); + if (NIL_P(ptr->string)) { + offset = 0; + } else { + offset = RSTRING_LEN(ptr->string); + } break; default: error_inval("invalid whence"); diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb index 002b946b..4c9cf374 100644 --- a/test/stringio/test_stringio.rb +++ b/test/stringio/test_stringio.rb @@ -70,6 +70,16 @@ def test_null assert_nil io.getc end + def test_seek_null + io = StringIO.new(nil) + assert_equal(0, io.seek(0, IO::SEEK_SET)) + assert_equal(0, io.pos) + assert_equal(0, io.seek(0, IO::SEEK_CUR)) + assert_equal(0, io.pos) + assert_equal(0, io.seek(0, IO::SEEK_END)) # This should not segfault + assert_equal(0, io.pos) + end + def test_truncate io = StringIO.new("") io.puts "abc" From ac0ad2321e2cc0e6c8a553cc6d664c29f57f2a87 Mon Sep 17 00:00:00 2001 From: koh-sh <34917718+koh-sh@users.noreply.github.com> Date: Sat, 9 Aug 2025 17:51:44 +0900 Subject: [PATCH 2/2] fix: prevent NullPointerException in StringIO#seek with SEEK_END on null device (JRuby) --- ext/java/org/jruby/ext/stringio/StringIO.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ext/java/org/jruby/ext/stringio/StringIO.java b/ext/java/org/jruby/ext/stringio/StringIO.java index 2002e2bb..83e331ec 100644 --- a/ext/java/org/jruby/ext/stringio/StringIO.java +++ b/ext/java/org/jruby/ext/stringio/StringIO.java @@ -1378,7 +1378,11 @@ private RubyFixnum seekCommon(ThreadContext context, int argc, IRubyObject arg0, offset += ptr.pos; break; case 2: - offset += ptr.string.size(); + if (ptr.string == null) { + offset += 0; + } else { + offset += ptr.string.size(); + } break; default: throw runtime.newErrnoEINVALError("invalid whence");