aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2015-08-28 18:52:41 -0400
committerJack Lloyd <[email protected]>2015-08-28 18:52:41 -0400
commited8a57e3b6f4af93dbb614429da2e1cfb2db5f3a (patch)
treefd0ab343fea63b9375d9a689a03ec263441e0784
parentf38b313be6db492584ee6e198894ccae49585565 (diff)
parent584cc4c0aca4b037fd04f8d37c53757aecf2062f (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.cpp22
-rw-r--r--src/tests/test_compression.cpp7
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");