diff options
author | Jack Lloyd <[email protected]> | 2015-08-28 18:52:41 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2015-08-28 18:52:41 -0400 |
commit | ed8a57e3b6f4af93dbb614429da2e1cfb2db5f3a (patch) | |
tree | fd0ab343fea63b9375d9a689a03ec263441e0784 | |
parent | f38b313be6db492584ee6e198894ccae49585565 (diff) | |
parent | 584cc4c0aca4b037fd04f8d37c53757aecf2062f (diff) |
Merge pull request #265 from tiwoc/compress-empty-buffer
Fix zlib error when compressing an empty buffer
-rw-r--r-- | src/lib/compression/compression.cpp | 22 | ||||
-rw-r--r-- | src/tests/test_compression.cpp | 7 |
2 files changed, 22 insertions, 7 deletions
diff --git a/src/lib/compression/compression.cpp b/src/lib/compression/compression.cpp index 6057f9408..ddbcd7cec 100644 --- a/src/lib/compression/compression.cpp +++ b/src/lib/compression/compression.cpp @@ -104,8 +104,16 @@ void Stream_Compression::process(secure_vector<byte>& buf, size_t offset, u32bit if(m_buffer.size() < buf.size() + offset) m_buffer.resize(buf.size() + offset); - m_stream->next_in(&buf[offset], buf.size() - offset); - m_stream->next_out(&m_buffer[offset], m_buffer.size() - offset); + // If the output buffer has zero length, .data() might return nullptr. This would + // make some compression algorithms (notably those provided by zlib) fail. + // Any small positive value works fine, but we choose 32 as it is the smallest power + // of two that is large enough to hold all the headers and trailers of the common + // formats, preventing further resizings to make room for output data. + if(m_buffer.size() == 0) + m_buffer.resize(32); + + m_stream->next_in(buf.data() + offset, buf.size() - offset); + m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset); while(true) { @@ -115,7 +123,7 @@ void Stream_Compression::process(secure_vector<byte>& buf, size_t offset, u32bit { const size_t added = 8 + m_buffer.size(); m_buffer.resize(m_buffer.size() + added); - m_stream->next_out(&m_buffer[m_buffer.size() - added], added); + m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added); } else if(m_stream->avail_in() == 0) { @@ -170,8 +178,8 @@ void Stream_Decompression::process(secure_vector<byte>& buf, size_t offset, u32b if(m_buffer.size() < buf.size() + offset) m_buffer.resize(buf.size() + offset); - m_stream->next_in(&buf[offset], buf.size() - offset); - m_stream->next_out(&m_buffer[offset], m_buffer.size() - offset); + m_stream->next_in(buf.data() + offset, buf.size() - offset); + m_stream->next_out(m_buffer.data() + offset, m_buffer.size() - offset); while(true) { @@ -189,14 +197,14 @@ void Stream_Decompression::process(secure_vector<byte>& buf, size_t offset, u32b // More data follows: try to process as a following stream const size_t read = (buf.size() - offset) - m_stream->avail_in(); start(); - m_stream->next_in(&buf[offset + read], buf.size() - offset - read); + m_stream->next_in(buf.data() + offset + read, buf.size() - offset - read); } if(m_stream->avail_out() == 0) { const size_t added = 8 + m_buffer.size(); m_buffer.resize(m_buffer.size() + added); - m_stream->next_out(&m_buffer[m_buffer.size() - added], added); + m_stream->next_out(m_buffer.data() + m_buffer.size() - added, added); } else if(m_stream->avail_in() == 0) { diff --git a/src/tests/test_compression.cpp b/src/tests/test_compression.cpp index b68262385..902455fc7 100644 --- a/src/tests/test_compression.cpp +++ b/src/tests/test_compression.cpp @@ -93,12 +93,15 @@ size_t test_compression() const size_t text_len = strlen(text_str); + const secure_vector<byte> empty; const secure_vector<byte> all_zeros(text_len, 0); const secure_vector<byte> random_binary = test_rng().random_vec(text_len); const byte* textb = reinterpret_cast<const byte*>(text_str); const secure_vector<byte> text(textb, textb + text_len); + const size_t c1_e = run_compression(*c1, *d, empty); + const size_t c9_e = run_compression(*c9, *d, empty); const size_t c1_z = run_compression(*c1, *d, all_zeros); const size_t c9_z = run_compression(*c9, *d, all_zeros); const size_t c1_r = run_compression(*c1, *d, random_binary); @@ -108,6 +111,10 @@ size_t test_compression() #define BOTAN_TEST_GTE(x, y, msg) if(x < y) { ++fails; std::cout << "FAIL: " << x << " " << y << " " << msg << std::endl; } + BOTAN_TEST_GTE(c1_e, 1, "Empty input compresses to non-empty output"); + BOTAN_TEST_GTE(c9_e, 1, "Empty input compresses to non-empty output"); + + BOTAN_TEST_GTE(c1_e, c9_e, "Level 9 compresses at least as well as level 1"); BOTAN_TEST_GTE(c1_z, c9_z, "Level 9 compresses at least as well as level 1"); BOTAN_TEST_GTE(c1_t, c9_t, "Level 9 compresses at least as well as level 1"); BOTAN_TEST_GTE(c1_r, c9_r, "Level 9 compresses at least as well as level 1"); |