From b3fc0e21b29fc17ccf81ed6a7919321443b0caf6 Mon Sep 17 00:00:00 2001 From: Shizuo Fujita Date: Thu, 19 Jun 2025 14:51:28 +0900 Subject: [PATCH] compressable: fix RuntimeError with large zstd compressed data Signed-off-by: Shizuo Fujita --- lib/fluent/plugin/compressable.rb | 4 ++-- test/plugin/test_compressable.rb | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/lib/fluent/plugin/compressable.rb b/lib/fluent/plugin/compressable.rb index 00aa915ba5..2ec2122931 100644 --- a/lib/fluent/plugin/compressable.rb +++ b/lib/fluent/plugin/compressable.rb @@ -79,9 +79,9 @@ def string_decompress_gzip(compressed_data) def string_decompress_zstd(compressed_data) io = StringIO.new(compressed_data) + reader = Zstd::StreamReader.new(io) out = '' loop do - reader = Zstd::StreamReader.new(io) # Zstd::StreamReader needs to specify the size of the buffer out << reader.read(1024) # Zstd::StreamReader doesn't provide unused data, so we have to manually adjust the position @@ -117,8 +117,8 @@ def io_decompress_gzip(input, output) end def io_decompress_zstd(input, output) + reader = Zstd::StreamReader.new(input) loop do - reader = Zstd::StreamReader.new(input) # Zstd::StreamReader needs to specify the size of the buffer v = reader.read(1024) output.write(v) diff --git a/test/plugin/test_compressable.rb b/test/plugin/test_compressable.rb index 96dfa318df..1c6788f6c5 100644 --- a/test/plugin/test_compressable.rb +++ b/test/plugin/test_compressable.rb @@ -83,5 +83,29 @@ def compress_assert_equal(expected, actual) assert_equal '', decompress('') assert_equal '', decompress('', output_io: StringIO.new) end + + test 'decompress large zstd compressed data' do + src1 = SecureRandom.random_bytes(1024) + src2 = SecureRandom.random_bytes(1024) + src3 = SecureRandom.random_bytes(1024) + + zstd_compressed_data = compress(src1, type: :zstd) + compress(src2, type: :zstd) + compress(src3, type: :zstd) + assert_equal src1 + src2 + src3, decompress(zstd_compressed_data, type: :zstd) + end + + test 'decompress large zstd compressed data with input_io and output_io' do + src1 = SecureRandom.random_bytes(1024) + src2 = SecureRandom.random_bytes(1024) + src3 = SecureRandom.random_bytes(1024) + + zstd_compressed_data = compress(src1, type: :zstd) + compress(src2, type: :zstd) + compress(src3, type: :zstd) + + input_io = StringIO.new(zstd_compressed_data) + output_io = StringIO.new + output_io.set_encoding(src1.encoding) + + decompress(input_io: input_io, output_io: output_io, type: :zstd) + assert_equal src1 + src2 + src3, output_io.string + end end end