From 824a2043f646db34f80d33b3e1065889582c95a2 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Mon, 14 Sep 2026 15:25:01 -0300 Subject: [PATCH] Split the GZIP tests by shape and cover more RFC edge cases Signed-off-by: Juan Cruz Viotti --- test/gzip/gzip_compress_format_test.cc | 43 +++++++++++++++++++++ test/gzip/gzip_decompress_error_test.cc | 8 ++++ test/gzip/gzip_decompress_test.cc | 51 +++++++++++++++++++++++++ 3 files changed, 102 insertions(+) diff --git a/test/gzip/gzip_compress_format_test.cc b/test/gzip/gzip_compress_format_test.cc index 1fe5c38bbb..518815e51c 100644 --- a/test/gzip/gzip_compress_format_test.cc +++ b/test/gzip/gzip_compress_format_test.cc @@ -26,6 +26,49 @@ TEST(compress_output_header_identifies_deflate_member) { EXPECT_EQ(compressed.at(3) & 0xe0, 0); } +TEST(compress_output_header_has_no_flags) { + const auto compressed{compress("hello world", 6)}; + EXPECT_EQ(compressed.at(3), 0x00); +} + +TEST(compress_output_header_has_no_modification_time) { + const auto compressed{compress("hello world", 6)}; + const std::vector modification_time{compressed.cbegin() + 4, + compressed.cbegin() + 8}; + const std::vector expected{0x00, 0x00, 0x00, 0x00}; + EXPECT_EQ(modification_time, expected); +} + +TEST(compress_output_header_at_level_0_marks_fastest_algorithm) { + const auto compressed{compress("hello world", 0)}; + EXPECT_EQ(compressed.at(8), 0x04); +} + +TEST(compress_output_header_at_level_1_marks_fastest_algorithm) { + const auto compressed{compress("hello world", 1)}; + EXPECT_EQ(compressed.at(8), 0x04); +} + +TEST(compress_output_header_at_level_6_marks_neither_fastest_nor_maximum) { + const auto compressed{compress("hello world", 6)}; + EXPECT_EQ(compressed.at(8), 0x00); +} + +TEST(compress_output_header_at_level_9_marks_maximum_compression) { + const auto compressed{compress("hello world", 9)}; + EXPECT_EQ(compressed.at(8), 0x02); +} + +TEST(compress_output_header_at_level_12_marks_maximum_compression) { + const auto compressed{compress("hello world", 12)}; + EXPECT_EQ(compressed.at(8), 0x02); +} + +TEST(compress_output_header_marks_unknown_operating_system) { + const auto compressed{compress("hello world", 6)}; + EXPECT_EQ(compressed.at(9), 0xff); +} + TEST(compress_output_trailer_of_empty_input) { const auto compressed{compress("", 1)}; const std::vector trailer{compressed.cend() - 8, diff --git a/test/gzip/gzip_decompress_error_test.cc b/test/gzip/gzip_decompress_error_test.cc index faa9047106..05b61d5335 100644 --- a/test/gzip/gzip_decompress_error_test.cc +++ b/test/gzip/gzip_decompress_error_test.cc @@ -542,6 +542,14 @@ TEST(dynamic_block_288_literal_length_codes) { EXPECT_GZIP_DECOMPRESS_ERROR(input, "Too many literal/length codes"); } +TEST(dynamic_block_match_without_distance_codes) { + const std::vector input{ + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0d, + 0xc0, 0x01, 0x09, 0x00, 0x00, 0x00, 0x80, 0x20, 0xff, 0xaf, 0x2e, + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + EXPECT_GZIP_DECOMPRESS_ERROR(input, "Invalid Huffman code"); +} + TEST(dynamic_block_unused_code_of_single_distance_code) { const std::vector input{ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0d, 0xe0, diff --git a/test/gzip/gzip_decompress_test.cc b/test/gzip/gzip_decompress_test.cc index 6a7b6d9b4c..55a98c1527 100644 --- a/test/gzip/gzip_decompress_test.cc +++ b/test/gzip/gzip_decompress_test.cc @@ -310,6 +310,15 @@ TEST(decompress_fixed_block_with_boundary_match_lengths) { EXPECT_GZIP_DECOMPRESS(input, std::string(1146, 'a')); } +// RFC 1951 section 3.2.5 assigns lengths 227 to 257 to length code 284, but +// like zlib the decoder accepts its extra bits reaching 258 +TEST(decompress_fixed_block_length_258_from_code_284) { + const std::vector input{ + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x4b, 0x1c, + 0xf9, 0x00, 0x00, 0x56, 0xfa, 0xc2, 0x34, 0x03, 0x01, 0x00, 0x00}; + EXPECT_GZIP_DECOMPRESS(input, std::string(259, 'a')); +} + TEST(decompress_fixed_block_overlapping_match) { const std::vector input{ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x8b, 0x88, @@ -784,6 +793,48 @@ TEST( EXPECT_GZIP_DECOMPRESS(input, std::string(65512, '\0') + "hello world"); } +TEST(decompress_second_member_fixed_header_spanning_stream_source_buffer) { + std::vector input{0x1f, 0x8b, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, + 0x01, 0xe7, 0xff, 0x18, 0x00}; + input.insert(input.end(), 65511, 0x00); + input.insert(input.end(), + {0xef, 0x77, 0x5e, 0xcb, 0xe7, 0xff, 0x00, 0x00, 0x1f, + 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x01, 0x0b, 0x00, 0xf4, 0xff, 0x68, 0x65, 0x6c, 0x6c, + 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x85, 0x11, + 0x4a, 0x0d, 0x0b, 0x00, 0x00, 0x00}); + EXPECT_GZIP_DECOMPRESS(input, std::string(65511, '\0') + "hello world"); +} + +TEST(decompress_second_member_header_checksum_spanning_stream_source_buffer) { + std::vector input{0x1f, 0x8b, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, + 0x01, 0xde, 0xff, 0x21, 0x00}; + input.insert(input.end(), 65502, 0x00); + input.insert(input.end(), + {0x91, 0x06, 0x5e, 0x62, 0xde, 0xff, 0x00, 0x00, 0x1f, + 0x8b, 0x08, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x90, 0xc9, 0x01, 0x0b, 0x00, 0xf4, 0xff, 0x68, 0x65, + 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, + 0x85, 0x11, 0x4a, 0x0d, 0x0b, 0x00, 0x00, 0x00}); + EXPECT_GZIP_DECOMPRESS(input, std::string(65502, '\0') + "hello world"); +} + +TEST(decompress_second_member_extra_length_spanning_stream_source_buffer) { + std::vector input{0x1f, 0x8b, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, + 0x01, 0xde, 0xff, 0x21, 0x00}; + input.insert(input.end(), 65502, 0x00); + input.insert(input.end(), + {0x91, 0x06, 0x5e, 0x62, 0xde, 0xff, 0x00, 0x00, 0x1f, + 0x8b, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x01, 0x0b, 0x00, 0xf4, 0xff, 0x68, 0x65, + 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, + 0x85, 0x11, 0x4a, 0x0d, 0x0b, 0x00, 0x00, 0x00}); + EXPECT_GZIP_DECOMPRESS(input, std::string(65502, '\0') + "hello world"); +} + TEST(decompress_fixed_block_spanning_stream_source_buffer) { std::vector input{0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x63};