From b013aae0c66fbef0faaab29ceeda18bae4fef608 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 9 Nov 2023 10:17:46 +0100 Subject: [PATCH] IO#read always check the provided buffer is mutable Otherwise you can have work in some circumstance but not in others. --- io.c | 3 ++- spec/ruby/core/io/read_spec.rb | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/io.c b/io.c index 28b5abb1c5..7ded212804 100644 --- a/io.c +++ b/io.c @@ -3276,9 +3276,10 @@ io_setstrbuf(VALUE *str, long len) } else { VALUE s = StringValue(*str); + rb_str_modify(s); + long clen = RSTRING_LEN(s); if (clen >= len) { - rb_str_modify(s); return FALSE; } len -= clen; diff --git a/spec/ruby/core/io/read_spec.rb b/spec/ruby/core/io/read_spec.rb index 996f70bf20..db11468ea4 100644 --- a/spec/ruby/core/io/read_spec.rb +++ b/spec/ruby/core/io/read_spec.rb @@ -299,6 +299,32 @@ describe "IO#read" do @io.read(10, buf).should == nil buf.should == '' + + buf = 'non-empty string' + + @io.read(nil, buf).should == "" + + buf.should == '' + + buf = 'non-empty string' + + @io.read(0, buf).should == "" + + buf.should == '' + end + + it "raise FrozenError if the output buffer is frozen" do + @io.read + -> { @io.read(0, 'frozen-string'.freeze) }.should raise_error(FrozenError) + -> { @io.read(1, 'frozen-string'.freeze) }.should raise_error(FrozenError) + -> { @io.read(nil, 'frozen-string'.freeze) }.should raise_error(FrozenError) + end + + ruby_bug "", ""..."3.3" do + it "raise FrozenError if the output buffer is frozen (2)" do + @io.read + -> { @io.read(1, ''.freeze) }.should raise_error(FrozenError) + end end it "consumes zero bytes when reading zero bytes" do