Skip to content

Commit

Permalink
[GR-18163] Fix implicit converting of argument to Integer in IO#seek …
Browse files Browse the repository at this point in the history
…and IO#pos=

PullRequest: truffleruby/3572
  • Loading branch information
andrykonchin committed Dec 12, 2022
2 parents 1b26e51 + 745efb1 commit 85a9b0e
Show file tree
Hide file tree
Showing 19 changed files with 40 additions and 26 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Compatibility:
* `rb_to_id()` should create a static `ID`, used by RMagick (@eregon).
* Resolve the current user home even when `$HOME` is not set (#2784, @eregon)
* Fix `IO#lineno=` and convert argument to `Integer` more strictly (#2786, @andrykonchin).
* Fix argument implicit convertion in `IO#pos=` and `IO#seek` methods (#2787, @andrykonchin).

Performance:

Expand Down
4 changes: 4 additions & 0 deletions spec/ruby/core/io/gets_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@
@io.gets(nil, 0).should == ""
@io.gets("", 0).should == ""
end

it "does not accept limit that doesn't fit in a C off_t" do
-> { @io.gets(2**128) }.should raise_error(RangeError)
end
end

describe "IO#gets" do
Expand Down
4 changes: 4 additions & 0 deletions spec/ruby/core/io/lineno_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@
-> { @io.lineno = nil }.should raise_error(TypeError, 'no implicit conversion from nil to integer')
end

it "does not accept Integers that don't fit in a C int" do
-> { @io.lineno = 2**32 }.should raise_error(RangeError)
end

it "sets the current line number to the given value" do
@io.lineno = count = 500

Expand Down
4 changes: 4 additions & 0 deletions spec/ruby/core/io/readline_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
it "returns an empty string when passed 0 as a limit" do
@io.readline(0).should == ""
end

it "does not accept Integers that don't fit in a C off_t" do
-> { @io.readline(2**128) }.should raise_error(RangeError)
end
end

describe "when passed separator and limit" do
Expand Down
4 changes: 4 additions & 0 deletions spec/ruby/core/io/readlines_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@
it "raises ArgumentError when passed 0 as a limit" do
-> { @io.readlines(0) }.should raise_error(ArgumentError)
end

it "does not accept Integers that don't fit in a C off_t" do
-> { @io.readlines(2**128) }.should raise_error(RangeError)
end
end

describe "when passed chomp" do
Expand Down
4 changes: 4 additions & 0 deletions spec/ruby/core/io/shared/each.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@
-> { @io.send(@method, 0){} }.should raise_error(ArgumentError)
end
end

it "does not accept Integers that don't fit in a C off_t" do
-> { @io.send(@method, 2**128){} }.should raise_error(RangeError)
end
end

describe "when passed a String containing one space as a separator" do
Expand Down
8 changes: 7 additions & 1 deletion spec/ruby/core/io/shared/pos.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,13 @@
end
end

it "does not accept Integers that don't fit in a C long" do
it "raises TypeError when cannot convert implicitly argument to Integer" do
File.open @fname do |io|
-> { io.send @method, Object.new }.should raise_error(TypeError, "no implicit conversion of Object into Integer")
end
end

it "does not accept Integers that don't fit in a C off_t" do
File.open @fname do |io|
-> { io.send @method, 2**128 }.should raise_error(RangeError)
end
Expand Down
4 changes: 4 additions & 0 deletions spec/ruby/core/io/shared/readlines.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@
(result ? result : ScratchPad.recorded).should == IOSpecs.lines
end

it "does not accept Integers that don't fit in a C off_t" do
-> { IO.send(@method, @name, 2**128, &@object) }.should raise_error(RangeError)
end

ruby_bug "#18767", ""..."3.3" do
describe "when passed limit" do
it "raises ArgumentError when passed 0 as a limit" do
Expand Down
2 changes: 1 addition & 1 deletion spec/ruby/core/io/sysseek_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
require_relative 'shared/pos'

describe "IO#sysseek" do
it_behaves_like :io_set_pos, :seek
it_behaves_like :io_set_pos, :sysseek
end

describe "IO#sysseek" do
Expand Down
1 change: 0 additions & 1 deletion spec/tags/core/io/pos_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/tags/core/io/read_nonblock_tags.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
fails:IO#read_nonblock reads after ungetc with data in the buffer
fails:IO#read_nonblock raises an exception after ungetc with data in the buffer and character conversion enabled
fails:IO#read_nonblock discards the existing buffer content upon error
fails:IO#read_nonblock preserves the encoding of the given buffer
5 changes: 0 additions & 5 deletions spec/tags/core/io/readpartial_tags.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
fails:IO#readpartial reads after ungetc without data in the buffer
fails:IO#readpartial discards the existing buffer content upon successful read
fails:IO#readpartial raises EOFError on EOF
fails:IO#readpartial discards the existing buffer content upon error
fails:IO#readpartial raises IOError if the stream is closed
fails:IO#readpartial preserves the encoding of the given buffer
3 changes: 1 addition & 2 deletions spec/tags/core/io/reopen_tags.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
fails:IO#reopen with a String affects exec/system/fork performed after it
fails:IO#reopen with an IO at EOF resets the EOF status to false
slow:IO#reopen with a String affects exec/system/fork performed after it
2 changes: 0 additions & 2 deletions spec/tags/core/io/seek_tags.txt

This file was deleted.

4 changes: 0 additions & 4 deletions spec/tags/core/io/set_encoding_tags.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1 @@
fails:IO#set_encoding when passed nil, nil with 'r' mode sets the encodings to the current Encoding defaults
fails:IO#set_encoding when passed nil, nil with 'r' mode allows the #external_encoding to change when Encoding.default_external is changed
fails:IO#set_encoding when passed nil, nil with 'rb' mode returns Encoding.default_external
fails:IO#set_encoding saves encoding options passed as a hash in the last argument
fails:IO#set_encoding raises ArgumentError when too many arguments are given
1 change: 0 additions & 1 deletion spec/tags/core/io/sysread_tags.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
fails:IO#sysread on a file reads normally even when called immediately after a buffered IO#read
fails:IO#sysread on a file immediately returns an empty string if the length argument is 0
fails:IO#sysread on a file immediately returns the given buffer if the length argument is 0
fails:IO#sysread on a file discards the existing buffer content upon error
Expand Down
1 change: 0 additions & 1 deletion spec/tags/core/io/sysseek_tags.txt

This file was deleted.

Empty file.
13 changes: 6 additions & 7 deletions src/main/ruby/truffleruby/core/io.rb
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ def self.foreach(name, separator=undefined, limit=undefined, **options, &block)
when Integer, nil
# do nothing
else
limit = Primitive.rb_to_int(limit)
limit = Primitive.rb_num2long(limit)
end
limit = nil if limit && limit < 0
chomp = Primitive.as_boolean(options[:chomp])
Expand Down Expand Up @@ -1284,7 +1284,7 @@ def inspect
ensure_open_and_readable

if limit
limit = Truffle::Type.coerce_to limit, Integer, :to_int
limit = Primitive.rb_num2long(limit)
sep = sep_or_limit ? StringValue(sep_or_limit) : nil
else
case sep_or_limit
Expand All @@ -1295,7 +1295,7 @@ def inspect
else
unless sep = Truffle::Type.rb_check_convert_type(sep_or_limit, String, :to_str)
sep = $/
limit = Truffle::Type.coerce_to sep_or_limit, Integer, :to_int
limit = Primitive.rb_num2long(sep_or_limit)
end
end
end
Expand Down Expand Up @@ -1639,7 +1639,7 @@ def pos
# f.pos = 17
# f.gets #=> "This is line two\n"
def pos=(offset)
seek offset, SEEK_SET
seek Primitive.rb_num2long(offset), SEEK_SET
end

##
Expand Down Expand Up @@ -2033,7 +2033,7 @@ def seek(amount, whence=SEEK_SET)
flush
reset_buffering

r = Truffle::POSIX.lseek(Primitive.io_fd(self), Integer(amount), whence)
r = Truffle::POSIX.lseek(Primitive.io_fd(self), Primitive.rb_num2long(amount), whence)
Errno.handle if r == -1
0
end
Expand Down Expand Up @@ -2251,8 +2251,7 @@ def sysseek(amount, whence=SEEK_SET)
ensure_open
raise IOError unless buffer_empty?

amount = Integer(amount)
r = Truffle::POSIX.lseek(Primitive.io_fd(self), amount, whence)
r = Truffle::POSIX.lseek(Primitive.io_fd(self), Primitive.rb_num2long(amount), whence)
Errno.handle if r == -1
r
end
Expand Down

0 comments on commit 85a9b0e

Please sign in to comment.