From 5ed4521f983526f2033b7650d3510a7d5fbbb52b Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Fri, 23 Oct 2026 22:00:34 -0700 Subject: [PATCH] Return the external encoding from GzipReader#external_encoding when converting With both external_encoding and internal_encoding given, enc holds the internal encoding and enc2 the external one, as rb_io_extract_encoding_option returns them, but #external_encoding returned enc. ```ruby io = StringIO.new(Zlib.gzip("abc")) Zlib::GzipReader.new(io, external_encoding: "ISO-8859-1", internal_encoding: "UTF-8").external_encoding # expected: # # actual: # ``` Fixes https://github.com/ruby/zlib/issues/81 Co-Authored-By: Claude Mythos 5.1 --- ext/zlib/zlib.c | 5 ++++- test/zlib/test_zlib.rb | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 982933b..87cf25e 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -4591,7 +4591,10 @@ rb_gzreader_readlines(int argc, VALUE *argv, VALUE obj) static VALUE rb_gzreader_external_encoding(VALUE self) { - return rb_enc_from_encoding(get_gzfile(self)->enc); + struct gzfile *gz = get_gzfile(self); + /* with a conversion set up, enc is the internal encoding and enc2 the + * external one (same convention as rb_io_extract_encoding_option) */ + return rb_enc_from_encoding(gz->enc2 ? gz->enc2 : gz->enc); } static VALUE diff --git a/test/zlib/test_zlib.rb b/test/zlib/test_zlib.rb index 1f9cb81..a74169c 100644 --- a/test/zlib/test_zlib.rb +++ b/test/zlib/test_zlib.rb @@ -1367,6 +1367,15 @@ def test_reader_wrap } end + def test_external_encoding_with_internal_encoding + pend "rb_io_extract_encoding_option ignores the encoding options on TruffleRuby" if RUBY_ENGINE == 'truffleruby' + r = Zlib::GzipReader.new(StringIO.new(Zlib.gzip("caf\xE9\n".b)), external_encoding: "ISO-8859-1", internal_encoding: "UTF-8") + assert_equal(Encoding::ISO_8859_1, r.external_encoding) + assert_equal("caf\u00E9\n", r.gets) + r = Zlib::GzipReader.new(StringIO.new(Zlib.gzip("caf\xE9\n".b)), external_encoding: "ISO-8859-1") + assert_equal(Encoding::ISO_8859_1, r.external_encoding) + end + def test_corrupted_header gz = Zlib::GzipWriter.new(StringIO.new(s = "".dup)) gz.orig_name = "X"