Fix Marshal.dump(closed_io) to raise TypeError and allow encoding on closed IO
Mashalling a closed IO object raised "closed stream (IOError)" before instead of TypeError. This changes IO#(in|ex)ternal_encoding to still return the encoding even if the underlying FD is closed. Fixes bug #18077
This commit is contained in:
parent
c527d278a3
commit
6594623f62
Notes:
git
2021-08-22 10:33:48 +09:00
6
io.c
6
io.c
@ -12092,9 +12092,8 @@ rb_io_s_copy_stream(int argc, VALUE *argv, VALUE io)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_io_external_encoding(VALUE io)
|
rb_io_external_encoding(VALUE io)
|
||||||
{
|
{
|
||||||
rb_io_t *fptr;
|
rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
|
||||||
if (fptr->encs.enc2) {
|
if (fptr->encs.enc2) {
|
||||||
return rb_enc_from_encoding(fptr->encs.enc2);
|
return rb_enc_from_encoding(fptr->encs.enc2);
|
||||||
}
|
}
|
||||||
@ -12117,9 +12116,8 @@ rb_io_external_encoding(VALUE io)
|
|||||||
static VALUE
|
static VALUE
|
||||||
rb_io_internal_encoding(VALUE io)
|
rb_io_internal_encoding(VALUE io)
|
||||||
{
|
{
|
||||||
rb_io_t *fptr;
|
rb_io_t *fptr = RFILE(rb_io_taint_check(io))->fptr;
|
||||||
|
|
||||||
GetOpenFile(io, fptr);
|
|
||||||
if (!fptr->encs.enc2) return Qnil;
|
if (!fptr->encs.enc2) return Qnil;
|
||||||
return rb_enc_from_encoding(io_read_encoding(fptr));
|
return rb_enc_from_encoding(io_read_encoding(fptr));
|
||||||
}
|
}
|
||||||
|
@ -94,8 +94,10 @@ describe "IO#external_encoding" do
|
|||||||
rm_r @name
|
rm_r @name
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises an IOError on closed stream" do
|
ruby_version_is '3.1' do
|
||||||
-> { IOSpecs.closed_io.external_encoding }.should raise_error(IOError)
|
it "can be retrieved from a closed stream" do
|
||||||
|
IOSpecs.closed_io.external_encoding.should equal(Encoding.default_external)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "with 'r' mode" do
|
describe "with 'r' mode" do
|
||||||
|
@ -113,8 +113,10 @@ describe "IO#internal_encoding" do
|
|||||||
Encoding.default_internal = @internal
|
Encoding.default_internal = @internal
|
||||||
end
|
end
|
||||||
|
|
||||||
it "raises an IOError on closed stream" do
|
ruby_version_is '3.1' do
|
||||||
-> { IOSpecs.closed_io.internal_encoding }.should raise_error(IOError)
|
it "can be retrieved from a closed stream" do
|
||||||
|
IOSpecs.closed_io.internal_encoding.should equal(Encoding.default_internal)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "with 'r' mode" do
|
describe "with 'r' mode" do
|
||||||
|
@ -3991,6 +3991,18 @@ __END__
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_marshal_closed_io
|
||||||
|
bug18077 = '[ruby-core:104927] [Bug #18077]'
|
||||||
|
r, w = IO.pipe
|
||||||
|
r.close; w.close
|
||||||
|
assert_raise(TypeError, bug18077) {Marshal.dump(r)}
|
||||||
|
|
||||||
|
class << r
|
||||||
|
undef_method :closed?
|
||||||
|
end
|
||||||
|
assert_raise(TypeError, bug18077) {Marshal.dump(r)}
|
||||||
|
end
|
||||||
|
|
||||||
def test_stdout_to_closed_pipe
|
def test_stdout_to_closed_pipe
|
||||||
EnvUtil.invoke_ruby(["-e", "loop {puts :ok}"], "", true, true) do
|
EnvUtil.invoke_ruby(["-e", "loop {puts :ok}"], "", true, true) do
|
||||||
|in_p, out_p, err_p, pid|
|
|in_p, out_p, err_p, pid|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user