diff options
Diffstat (limited to 'test/zlib/test_zlib.rb')
| -rw-r--r-- | test/zlib/test_zlib.rb | 85 |
1 files changed, 84 insertions, 1 deletions
diff --git a/test/zlib/test_zlib.rb b/test/zlib/test_zlib.rb index 5a8463ad8e..48b8f172ff 100644 --- a/test/zlib/test_zlib.rb +++ b/test/zlib/test_zlib.rb @@ -9,6 +9,9 @@ require 'securerandom' begin require 'zlib' rescue LoadError +else + z = "/zlib.#{RbConfig::CONFIG["DLEXT"]}" + LOADED_ZLIB, = $".select {|f| f.end_with?(z)} end if defined? Zlib @@ -879,6 +882,25 @@ if defined? Zlib assert_equal(-1, r.pos, "[ruby-core:81488][Bug #13616]") end + def test_ungetc_buffer_underflow + initial_bufsize = 1024 + payload = "A" * initial_bufsize + gzip_io = StringIO.new + Zlib::GzipWriter.wrap(gzip_io) { |gz| gz.write(payload) } + compressed = gzip_io.string + + reader = Zlib::GzipReader.new(StringIO.new(compressed)) + reader.read(1) + overflow_bytes = "B" * (initial_bufsize) + reader.ungetc(overflow_bytes) + data = reader.read(overflow_bytes.bytesize) + assert_equal overflow_bytes.bytesize, data.bytesize, data + assert_empty data.delete("B"), data + data = reader.read() + assert_equal initial_bufsize - 1, data.bytesize, data + assert_empty data.delete("A"), data + end + def test_open Tempfile.create("test_zlib_gzip_reader_open") {|t| t.close @@ -1263,6 +1285,36 @@ if defined? Zlib end } end + + # Test for signal interrupt bug: Z_BUF_ERROR with avail_out > 0 + # This reproduces the issue where thread wakeup during GzipReader operations + # can cause Z_BUF_ERROR to be raised incorrectly + def test_thread_wakeup_interrupt + pend 'fails' if RUBY_ENGINE == 'truffleruby' + content = SecureRandom.base64(5000) + gzipped = Zlib.gzip(content) + + 1000.times do + thr = Thread.new do + loop do + Zlib::GzipReader.new(StringIO.new(gzipped)).read + end + end + + # Wakeup the thread multiple times to trigger interrupts + 10.times do + thr.wakeup + Thread.pass + end + + # Give thread a moment to process + sleep 0.001 + + # Clean up + thr.kill + thr.join + end + end end class TestZlibGzipWriter < Test::Unit::TestCase @@ -1525,11 +1577,42 @@ if defined? Zlib end def test_gunzip_no_memory_leak - assert_no_memory_leak(%[-rzlib], "#{<<~"{#"}", "#{<<~'};'}") + assert_no_memory_leak(%W[-r#{LOADED_ZLIB}], "#{<<~"{#"}", "#{<<~'};'}") d = Zlib.gzip("data") {# 10_000.times {Zlib.gunzip(d)} }; end + + # Test for signal interrupt bug: Z_BUF_ERROR with avail_out > 0 + # This reproduces the issue where thread wakeup during GzipReader operations + # can cause Z_BUF_ERROR to be raised incorrectly + def test_thread_wakeup_interrupt + pend 'fails' if RUBY_ENGINE == 'truffleruby' + + content = SecureRandom.base64(5000) + gzipped = Zlib.gzip(content) + + 1000.times do + thr = Thread.new do + loop do + Zlib::GzipReader.new(StringIO.new(gzipped)).read + end + end + + # Wakeup the thread multiple times to trigger interrupts + 10.times do + thr.wakeup + Thread.pass + end + + # Give thread a moment to process + sleep 0.001 + + # Clean up + thr.kill + thr.join + end + end end end |
