From 740eddb069d31cf916ccd90b4dcaaca8f13dcb9b Mon Sep 17 00:00:00 2001 From: Andrew Konchin Date: Fri, 28 Jun 2024 20:25:27 +0300 Subject: [PATCH] Fix StringIO#initialize and preserve initial string's encoding when mode is `w` so the initial string is truncated * close https://github.com/oracle/truffleruby/issues/3599 --- CHANGELOG.md | 1 + lib/truffle/stringio.rb | 4 ++-- spec/ruby/library/stringio/initialize_spec.rb | 20 +++++++++++++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 100324b302a0..026b2abc2c15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ Compatibility: * Fix `Enumerable#reduce` to handle non-Symbol method name parameter (#2931, @andrykonchin). * Fix `RangeError` message to match CRuby for `Integer#chr` called with invalid codepoint argument (#2795, @andrykonchin). * Joni has been updated from 2.1.44 to 2.2.1 (@andrykonchin). +* Fix `StringIO#initialize` and preserve initial string's encoding when mode is `w` so the initial string is truncated (#3599, @andrykonchin). Performance: diff --git a/lib/truffle/stringio.rb b/lib/truffle/stringio.rb index 702e02a1e5cf..a3e625554f40 100644 --- a/lib/truffle/stringio.rb +++ b/lib/truffle/stringio.rb @@ -691,7 +691,7 @@ def yaml_initialize(type, val) d = @__data__ # no sync, only called from initialize raise Errno::EACCES, 'Permission denied' if @writable && d.string.frozen? - d.string.replace('') if truncate + d.string.replace(''.force_encoding(d.string.encoding)) if truncate end private def mode_from_integer(mode) @@ -708,7 +708,7 @@ def yaml_initialize(type, val) end @append = true if (mode & IO::APPEND) != 0 - d.string.replace('') if (mode & IO::TRUNC) != 0 + d.string.replace(''.force_encoding(d.string.encoding)) if (mode & IO::TRUNC) != 0 end private def getline(arg_error, sep, limit, chomp = false) diff --git a/spec/ruby/library/stringio/initialize_spec.rb b/spec/ruby/library/stringio/initialize_spec.rb index ad067a0be17c..49489acf0cd5 100644 --- a/spec/ruby/library/stringio/initialize_spec.rb +++ b/spec/ruby/library/stringio/initialize_spec.rb @@ -130,6 +130,26 @@ -> { @io.send(:initialize, str, "w") }.should raise_error(Errno::EACCES) -> { @io.send(:initialize, str, "a") }.should raise_error(Errno::EACCES) end + + it "truncates all the content if passed w mode" do + io = StringIO.allocate + source = +"example".encode(Encoding::ISO_8859_1); + + io.send(:initialize, source, "w") + + io.string.should.empty? + io.string.encoding.should == Encoding::ISO_8859_1 + end + + it "truncates all the content if passed IO::TRUNC mode" do + io = StringIO.allocate + source = +"example".encode(Encoding::ISO_8859_1); + + io.send(:initialize, source, IO::TRUNC) + + io.string.should.empty? + io.string.encoding.should == Encoding::ISO_8859_1 + end end describe "StringIO#initialize when passed [Object]" do