From 6c60006de5cfd75f10a1b4a3d822e2de41d22db6 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 10 Feb 2023 10:33:53 -0800 Subject: Raise ArgumentError if IO.read is provided negative offset Fixes [Bug #19380] --- io.c | 4 ++++ spec/ruby/core/io/read_spec.rb | 15 ++++++++++++--- test/ruby/test_io.rb | 3 +++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/io.c b/io.c index a3dfa027d4..a023039209 100644 --- a/io.c +++ b/io.c @@ -12125,9 +12125,13 @@ static VALUE rb_io_s_read(int argc, VALUE *argv, VALUE io) { VALUE opt, offset; + long off; struct foreach_arg arg; argc = rb_scan_args(argc, argv, "13:", NULL, NULL, &offset, NULL, &opt); + if (!NIL_P(offset) && (off = NUM2LONG(offset)) < 0) { + rb_raise(rb_eArgError, "negative offset %ld given", off); + } open_key_args(io, argc, argv, opt, &arg); if (NIL_P(arg.io)) return Qnil; if (!NIL_P(offset)) { diff --git a/spec/ruby/core/io/read_spec.rb b/spec/ruby/core/io/read_spec.rb index 0184c88f44..8bffd50876 100644 --- a/spec/ruby/core/io/read_spec.rb +++ b/spec/ruby/core/io/read_spec.rb @@ -128,9 +128,18 @@ describe "IO.read" do -> { IO.read @fname, -1 }.should raise_error(ArgumentError) end - it "raises an Errno::EINVAL when not passed a valid offset" do - -> { IO.read @fname, 0, -1 }.should raise_error(Errno::EINVAL) - -> { IO.read @fname, -1, -1 }.should raise_error(Errno::EINVAL) + ruby_version_is ''...'3.3' do + it "raises an Errno::EINVAL when not passed a valid offset" do + -> { IO.read @fname, 0, -1 }.should raise_error(Errno::EINVAL) + -> { IO.read @fname, -1, -1 }.should raise_error(Errno::EINVAL) + end + end + + ruby_version_is '3.3' do + it "raises an ArgumentError when not passed a valid offset" do + -> { IO.read @fname, 0, -1 }.should raise_error(ArgumentError) + -> { IO.read @fname, -1, -1 }.should raise_error(ArgumentError) + end end it "uses the external encoding specified via the :external_encoding option" do diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb index 0716dd7bf9..f57dee4261 100644 --- a/test/ruby/test_io.rb +++ b/test/ruby/test_io.rb @@ -2866,6 +2866,9 @@ class TestIO < Test::Unit::TestCase assert_equal("foo\nbar\nbaz\n", File.read(t.path)) assert_equal("foo\nba", File.read(t.path, 6)) assert_equal("bar\n", File.read(t.path, 4, 4)) + + assert_raise(ArgumentError) { File.read(t.path, -1) } + assert_raise(ArgumentError) { File.read(t.path, 1, -1) } } end -- cgit v1.2.3