diff options
author | NAKAMURA Usaku <usa@ruby-lang.org> | 2022-03-05 21:38:48 +0900 |
---|---|---|
committer | NAKAMURA Usaku <usa@ruby-lang.org> | 2022-03-05 21:38:48 +0900 |
commit | f740ffb81f3ef11526add528583b0cbfce28af67 (patch) | |
tree | 18931c618c80b9ac334ca2faf1f7d8211a12ea61 /test | |
parent | 1034b6e7ba9442320e16c260d634d4c64d5e62bf (diff) |
merge revision(s) b3d62a77d928eff01268ca7fa1c1c0966702926d [Backport #17803]
[ruby/zlib] Synchronize access to zstream to prevent segfault in
multithreaded use
I'm not sure whether this handles all multithreaded use cases,
but this handles the example that crashes almost immediately
and does 10,000,000 total deflates using 100 separate threads.
To prevent the tests from taking forever, the committed test
for this uses only 10,000 deflates across 10 separate threads,
which still causes a segfault in the previous implementation
almost immediately.
Fixes [Bug #17803]
https://github.com/ruby/zlib/commit/4b1023b3f2
---
ext/zlib/zlib.c | 33 ++++++++++++++++++++++++++-
test/zlib/test_zlib.rb | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 93 insertions(+), 1 deletion(-)
Diffstat (limited to 'test')
-rw-r--r-- | test/zlib/test_zlib.rb | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/test/zlib/test_zlib.rb b/test/zlib/test_zlib.rb index 7d703d15e4..e4baa44ecb 100644 --- a/test/zlib/test_zlib.rb +++ b/test/zlib/test_zlib.rb @@ -3,6 +3,7 @@ require 'test/unit' require 'stringio' require 'tempfile' +require 'securerandom' begin require 'zlib' @@ -443,6 +444,61 @@ if defined? Zlib assert_raise(Zlib::StreamError) { z.set_dictionary("foo") } z.close end + + def test_multithread_deflate + zd = Zlib::Deflate.new + s = "x" * 10000 + (0...10).map do |x| + Thread.new do + 1000.times { zd.deflate(s) } + end + end.each do |th| + th.join + end + ensure + zd&.finish + zd&.close + end + + def test_multithread_inflate + zi = Zlib::Inflate.new + s = Zlib.deflate("x" * 10000) + (0...10).map do |x| + Thread.new do + 1000.times { zi.inflate(s) } + end + end.each do |th| + th.join + end + ensure + zi&.finish + zi&.close + end + + def test_recursive_deflate + zd = Zlib::Deflate.new + s = SecureRandom.random_bytes(1024**2) + assert_raise(Zlib::BufError) do + zd.deflate(s) do + zd.deflate(s) + end + end + ensure + zd&.finish + zd&.close + end + + def test_recursive_inflate + zi = Zlib::Inflate.new + s = Zlib.deflate(SecureRandom.random_bytes(1024**2)) + assert_raise(Zlib::DataError) do + zi.inflate(s) do + zi.inflate(s) + end + end + ensure + zi&.close + end end class TestZlibGzipFile < Test::Unit::TestCase |