Commit eb9d7cd7 authored by Nicholas Ormrod's avatar Nicholas Ormrod Committed by Dave Watson

zlib compression fails on large IOBufs

Summary:
If a single IOBuf has size exceeding 2^32, then our zlib
compression algorithm fails. Specifically, zlib z_stream.avail_in is
only 32 bytes (I think it's a long?
http://www.gzip.org/zlib/zlib_faq.html#faq32), and so a too-big IOBuf
will overflow the z_stream and cause data loss.

This diff breaks up large IOBufs into smaller chunks.

Test Plan:
fbconfig -r folly && fbmake runtests

Also compressed biggrep's configerator blob, which is how this bug was
caught. It now works. See the associated task.

Reviewed By: robbert@fb.com

Subscribers: trunkagent, sdwilsh, njormrod, folly-diffs@

FB internal diff: D1702925

Tasks: 5648445

Signature: t1:1702925:1416958232:459d498ff1db13e1a20766855e6f2f97da8cde8c
parent 607e323f
...@@ -553,21 +553,25 @@ std::unique_ptr<IOBuf> ZlibCodec::doCompress(const IOBuf* data) { ...@@ -553,21 +553,25 @@ std::unique_ptr<IOBuf> ZlibCodec::doCompress(const IOBuf* data) {
defaultBufferLength)); defaultBufferLength));
for (auto& range : *data) { for (auto& range : *data) {
if (range.empty()) { uint64_t remaining = range.size();
continue; uint64_t written = 0;
} while (remaining) {
uint32_t step = (remaining > maxSingleStepLength ?
stream.next_in = const_cast<uint8_t*>(range.data()); maxSingleStepLength : remaining);
stream.avail_in = range.size(); stream.next_in = const_cast<uint8_t*>(range.data() + written);
stream.avail_in = step;
while (stream.avail_in != 0) { remaining -= step;
if (stream.avail_out == 0) { written += step;
out->prependChain(addOutputBuffer(&stream, defaultBufferLength));
while (stream.avail_in != 0) {
if (stream.avail_out == 0) {
out->prependChain(addOutputBuffer(&stream, defaultBufferLength));
}
rc = deflate(&stream, Z_NO_FLUSH);
CHECK_EQ(rc, Z_OK) << stream.msg;
} }
rc = deflate(&stream, Z_NO_FLUSH);
CHECK_EQ(rc, Z_OK) << stream.msg;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment