[ruby/stringio] Raise an error if encoding conversion not succeeded

As `rb_str_conv_enc()` returns the argument string object itself
unchanged when any conversion failed, check the incompatibility in
that case.

Fixes https://github.com/ruby/stringio/issues/13

https://github.com/ruby/stringio/commit/ede6bdcc71
This commit is contained in:
Nobuyoshi Nakada 2020-07-18 23:52:27 +09:00
parent 840115bf46
commit 6ff9604f85
Notes: git 2020-07-20 14:59:47 +09:00
2 changed files with 31 additions and 1 deletions

View File

@ -1435,7 +1435,12 @@ strio_write(VALUE self, VALUE str)
enc = get_enc(ptr); enc = get_enc(ptr);
enc2 = rb_enc_get(str); enc2 = rb_enc_get(str);
if (enc != enc2 && enc != ascii8bit) { if (enc != enc2 && enc != ascii8bit) {
str = rb_str_conv_enc(str, enc2, enc); VALUE converted = rb_str_conv_enc(str, enc2, enc);
if (converted == str && enc2 != ascii8bit) { /* conversion failed */
rb_enc_check(rb_enc_from_encoding(enc), str);
UNREACHABLE;
}
str = converted;
} }
len = RSTRING_LEN(str); len = RSTRING_LEN(str);
if (len == 0) return 0; if (len == 0) return 0;

View File

@ -187,6 +187,31 @@ class TestStringIO < Test::Unit::TestCase
assert_equal(Encoding::UTF_8, s.encoding, "honor the original encoding over ASCII-8BIT") assert_equal(Encoding::UTF_8, s.encoding, "honor the original encoding over ASCII-8BIT")
end end
def test_write_encoding_conversion
convertible = "\u{3042}"
inconvertible = "\u{1f363}"
conversion_encoding = Encoding::Windows_31J
s = StringIO.new.set_encoding(conversion_encoding)
s.write(convertible)
assert_equal(conversion_encoding, s.string.encoding)
all_assertions do |a|
[
inconvertible,
convertible + inconvertible,
[convertible, inconvertible],
["a", inconvertible],
].each do |data|
a.for(data.inspect) do
s = StringIO.new.set_encoding(conversion_encoding)
assert_raise(Encoding::CompatibilityError) do
s.write(*data)
end
end
end
end
end
def test_write_integer_overflow def test_write_integer_overflow
f = StringIO.new f = StringIO.new
f.pos = RbConfig::LIMITS["LONG_MAX"] f.pos = RbConfig::LIMITS["LONG_MAX"]