Skip to content

Commit ede6bdc

Browse files
committed
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 #13
1 parent 272492d commit ede6bdc

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

ext/stringio/stringio.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1435,7 +1435,12 @@ strio_write(VALUE self, VALUE str)
14351435
enc = get_enc(ptr);
14361436
enc2 = rb_enc_get(str);
14371437
if (enc != enc2 && enc != ascii8bit) {
1438-
str = rb_str_conv_enc(str, enc2, enc);
1438+
VALUE converted = rb_str_conv_enc(str, enc2, enc);
1439+
if (converted == str && enc2 != ascii8bit) { /* conversion failed */
1440+
rb_enc_check(rb_enc_from_encoding(enc), str);
1441+
UNREACHABLE;
1442+
}
1443+
str = converted;
14391444
}
14401445
len = RSTRING_LEN(str);
14411446
if (len == 0) return 0;

test/stringio/test_stringio.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,31 @@ def test_write_encoding
187187
assert_equal(Encoding::UTF_8, s.encoding, "honor the original encoding over ASCII-8BIT")
188188
end
189189

190+
def test_write_encoding_conversion
191+
convertible = "\u{3042}"
192+
inconvertible = "\u{1f363}"
193+
conversion_encoding = Encoding::Windows_31J
194+
195+
s = StringIO.new.set_encoding(conversion_encoding)
196+
s.write(convertible)
197+
assert_equal(conversion_encoding, s.string.encoding)
198+
all_assertions do |a|
199+
[
200+
inconvertible,
201+
convertible + inconvertible,
202+
[convertible, inconvertible],
203+
["a", inconvertible],
204+
].each do |data|
205+
a.for(data.inspect) do
206+
s = StringIO.new.set_encoding(conversion_encoding)
207+
assert_raise(Encoding::CompatibilityError) do
208+
s.write(*data)
209+
end
210+
end
211+
end
212+
end
213+
end
214+
190215
def test_write_integer_overflow
191216
f = StringIO.new
192217
f.pos = RbConfig::LIMITS["LONG_MAX"]

0 commit comments

Comments
 (0)