diff --git a/llvm/lib/Support/Compression.cpp b/llvm/lib/Support/Compression.cpp --- a/llvm/lib/Support/Compression.cpp +++ b/llvm/lib/Support/Compression.cpp @@ -46,18 +46,29 @@ bool zlib::isAvailable() { return true; } -Error zlib::compress(StringRef InputBuffer, - SmallVectorImpl &CompressedBuffer, int Level) { - unsigned long CompressedSize = ::compressBound(InputBuffer.size()); - CompressedBuffer.resize_for_overwrite(CompressedSize); - int Res = - ::compress2((Bytef *)CompressedBuffer.data(), &CompressedSize, - (const Bytef *)InputBuffer.data(), InputBuffer.size(), Level); +Error zlib::compress(StringRef In, SmallVectorImpl &Out, int Level) { + z_stream s = {}; + // Default parameters with custom Level. + deflateInit2(&s, Level, Z_DEFLATED, 15, 8, Z_DEFAULT_STRATEGY); + s.next_in = + const_cast(reinterpret_cast(In.data())); + s.avail_in = In.size(); + Out.resize_for_overwrite(std::max(In.size() / 2, 64)); + size_t Pos = 0; + do { + if (Pos == Out.size()) + Out.resize_for_overwrite(Out.size() * 3 / 2); + s.next_out = reinterpret_cast(Out.data()) + Pos; + s.avail_out = Out.size() - Pos; + (void)deflate(&s, Z_FINISH); + Pos = s.next_out - reinterpret_cast(Out.data()); + } while (s.avail_out == 0); + assert(s.avail_in == 0); + Out.truncate(Pos); // Tell MemorySanitizer that zlib output buffer is fully initialized. // This avoids a false report when running LLVM with uninstrumented ZLib. - __msan_unpoison(CompressedBuffer.data(), CompressedSize); - CompressedBuffer.truncate(CompressedSize); - return Res ? createError(convertZlibCodeToString(Res)) : Error::success(); + __msan_unpoison(Out.data(), Pos); + return Error::success(); } Error zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer,