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,12 +553,15 @@ std::unique_ptr<IOBuf> ZlibCodec::doCompress(const IOBuf* data) { ...@@ -553,12 +553,15 @@ 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;
remaining -= step;
written += step;
while (stream.avail_in != 0) { while (stream.avail_in != 0) {
if (stream.avail_out == 0) { if (stream.avail_out == 0) {
...@@ -570,6 +573,7 @@ std::unique_ptr<IOBuf> ZlibCodec::doCompress(const IOBuf* data) { ...@@ -570,6 +573,7 @@ std::unique_ptr<IOBuf> ZlibCodec::doCompress(const IOBuf* data) {
CHECK_EQ(rc, Z_OK) << stream.msg; CHECK_EQ(rc, Z_OK) << stream.msg;
} }
} }
}
do { do {
if (stream.avail_out == 0) { if (stream.avail_out == 0) {
......
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