From 29c02709cd68a122c5db4f58ec0e901fe3d507cc Mon Sep 17 00:00:00 2001 From: Dylan Thacker-Smith Date: Fri, 24 Feb 2017 17:26:54 -0500 Subject: Add missing gzip footer check in ActiveSupport::Gzip.decompress A gzip file has a checksum and length for the decompressed data in its footer which isn't checked by just calling Zlib::GzipReader#read. Calling Zlib::GzipReader#close must be called after reading to the end of the file causes this check to be done, which is done by Zlib::GzipReader.wrap after its block is called. --- actionpack/test/dispatch/static_test.rb | 2 +- activesupport/CHANGELOG.md | 4 ++++ activesupport/lib/active_support/gzip.rb | 2 +- activesupport/test/gzip_test.rb | 10 ++++++++++ 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb index bd8318f5f6..3082d1072b 100644 --- a/actionpack/test/dispatch/static_test.rb +++ b/actionpack/test/dispatch/static_test.rb @@ -224,7 +224,7 @@ module StaticTests def assert_gzip(file_name, response) expected = File.read("#{FIXTURE_LOAD_PATH}/#{public_path}" + file_name) - actual = Zlib::GzipReader.new(StringIO.new(response.body)).read + actual = ActiveSupport::Gzip.decompress(response.body) assert_equal expected, actual end diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index 0f43b1256f..bad83e0287 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,5 +1,9 @@ ## Rails 5.1.0.beta1 (February 23, 2017) ## +* `ActiveSupport::Gzip.decompress` now checks checksum and length in footer. + + *Dylan Thacker-Smith* + * Cache `ActiveSupport::TimeWithZone#to_datetime` before freezing. *Adam Rice* diff --git a/activesupport/lib/active_support/gzip.rb b/activesupport/lib/active_support/gzip.rb index 84eef6a623..95a86889ec 100644 --- a/activesupport/lib/active_support/gzip.rb +++ b/activesupport/lib/active_support/gzip.rb @@ -21,7 +21,7 @@ module ActiveSupport # Decompresses a gzipped string. def self.decompress(source) - Zlib::GzipReader.new(StringIO.new(source)).read + Zlib::GzipReader.wrap(StringIO.new(source), &:read) end # Compresses a string using gzip. diff --git a/activesupport/test/gzip_test.rb b/activesupport/test/gzip_test.rb index f51d3cdf65..33e0cd2a04 100644 --- a/activesupport/test/gzip_test.rb +++ b/activesupport/test/gzip_test.rb @@ -30,4 +30,14 @@ class GzipTest < ActiveSupport::TestCase assert_equal true, (gzipped_by_best_compression.bytesize < gzipped_by_speed.bytesize) end + + def test_decompress_checks_crc + compressed = ActiveSupport::Gzip.compress("Hello World") + first_crc_byte_index = compressed.bytesize - 8 + compressed.setbyte(first_crc_byte_index, compressed.getbyte(first_crc_byte_index) ^ 0xff) + + assert_raises(Zlib::GzipFile::CRCError) do + ActiveSupport::Gzip.decompress(compressed) + end + end end -- cgit v1.2.3