summaryrefslogtreecommitdiff
path: root/test/zlib/test_zlib.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/zlib/test_zlib.rb')
-rw-r--r--test/zlib/test_zlib.rb85
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