std::unique_ptr<IOBuf> ZlibCodec::doUncompress(const IOBuf* data, uint64_t uncompressedLength) { z_stream stream; stream.zalloc = nullptr; stream.zfree = nullptr; stream.opaque = nullptr; // "The windowBits parameter is the base two logarithm of the maximum window // size (...) The default value is 15 (...) add 16 to decode only the gzip // format (the zlib format will return a Z_DATA_ERROR)." int windowBits = 15 + (type() == CodecType::GZIP ? 16 : 0); int rc = inflateInit2(&stream, windowBits); if (rc != Z_OK) { throw std::runtime_error(to<std::string>( "ZlibCodec: inflateInit error: ", rc, ": ", stream.msg)); } stream.next_in = stream.next_out = nullptr; stream.avail_in = stream.avail_out = 0; stream.total_in = stream.total_out = 0; bool success = false; SCOPE_EXIT { int rc = inflateEnd(&stream); // If we're here because of an exception, it's okay if some data // got dropped. CHECK(rc == Z_OK || (!success && rc == Z_DATA_ERROR)) << rc << ": " << stream.msg; }; // Max 64MiB in one go constexpr uint32_t maxSingleStepLength = uint32_t(64) << 20; // 64MiB constexpr uint32_t defaultBufferLength = uint32_t(4) << 20; // 4MiB auto out = addOutputBuffer( &stream, ((uncompressedLength != UNKNOWN_UNCOMPRESSED_LENGTH && uncompressedLength <= maxSingleStepLength) ? uncompressedLength : defaultBufferLength)); bool streamEnd = false; for (auto& range : *data) { if (range.empty()) { continue; } stream.next_in = const_cast<uint8_t*>(range.data()); stream.avail_in = range.size(); while (stream.avail_in != 0) { if (streamEnd) { throw std::runtime_error(to<std::string>( "ZlibCodec: junk after end of data")); } streamEnd = doInflate(&stream, out.get(), defaultBufferLength); } } while (!streamEnd) { streamEnd = doInflate(&stream, out.get(), defaultBufferLength); } out->prev()->trimEnd(stream.avail_out); if (uncompressedLength != UNKNOWN_UNCOMPRESSED_LENGTH && uncompressedLength != stream.total_out) { throw std::runtime_error(to<std::string>( "ZlibCodec: invalid uncompressed length")); } success = true; // we survived return out; }
std::unique_ptr<IOBuf> LZMA2Codec::doUncompress(const IOBuf* data, uint64_t uncompressedLength) { lzma_ret rc; lzma_stream stream = LZMA_STREAM_INIT; rc = lzma_auto_decoder(&stream, std::numeric_limits<uint64_t>::max(), 0); if (rc != LZMA_OK) { throw std::runtime_error(folly::to<std::string>( "LZMA2Codec: lzma_auto_decoder error: ", rc)); } SCOPE_EXIT { lzma_end(&stream); }; // Max 64MiB in one go constexpr uint32_t maxSingleStepLength = uint32_t(64) << 20; // 64MiB constexpr uint32_t defaultBufferLength = uint32_t(4) << 20; // 4MiB folly::io::Cursor cursor(data); uint64_t actualUncompressedLength; if (encodeSize()) { actualUncompressedLength = decodeVarintFromCursor(cursor); if (uncompressedLength != UNKNOWN_UNCOMPRESSED_LENGTH && uncompressedLength != actualUncompressedLength) { throw std::runtime_error("LZMA2Codec: invalid uncompressed length"); } } else { actualUncompressedLength = uncompressedLength; DCHECK_NE(actualUncompressedLength, UNKNOWN_UNCOMPRESSED_LENGTH); } auto out = addOutputBuffer( &stream, (actualUncompressedLength <= maxSingleStepLength ? actualUncompressedLength : defaultBufferLength)); bool streamEnd = false; auto buf = cursor.peekBytes(); while (!buf.empty()) { stream.next_in = const_cast<uint8_t*>(buf.data()); stream.avail_in = buf.size(); while (stream.avail_in != 0) { if (streamEnd) { throw std::runtime_error(to<std::string>( "LZMA2Codec: junk after end of data")); } streamEnd = doInflate(&stream, out.get(), defaultBufferLength); } cursor.skip(buf.size()); buf = cursor.peekBytes(); } while (!streamEnd) { streamEnd = doInflate(&stream, out.get(), defaultBufferLength); } out->prev()->trimEnd(stream.avail_out); if (actualUncompressedLength != stream.total_out) { throw std::runtime_error(to<std::string>( "LZMA2Codec: invalid uncompressed length")); } return out; }
int displayEmbeddedProdAndBsp(void) { int result; int returnVal = 0; char *p; char *p1, *p2; char productName[64]; char bspName[64]; int prodStringFound = 0; int bspStringFound = 0; /* * First, perform the inflate from the compressed buffer to the * application buffer */ if ((result = doInflate(cmpBuffer, appBuffer)) != ERR_OK) return(returnVal); /* * In the application buffer, look for both search patterns so * as to locate the Product and BSP names. Use memchr to find the * first character ('T'), then compare rest of string. If not found, * resume search for next occurrence of 'T'. */ p = memchr(appBuffer, TEE, appBufferSize); if (p == NULL) { returnVal = 0; goto fail; } while (!prodStringFound && (p != NULL)) { if (memcmp(p, PROD_SEARCH_STRING, strlen(PROD_SEARCH_STRING)) == 0) { prodStringFound = 1; returnVal = 1; p1 = strchr(p, COLON) + 1; if (p1 == NULL) { returnVal = 0; goto fail; } for (p2 = productName; (*p1 != SPACE) && (*p1 != NUL); p1++, p2++) *p2 = *p1; *p2 = NUL; } else { p = memchr(p + 1, TEE, appBufferSize - (p - appBuffer)); } } if (returnVal) { p = memchr(appBuffer, TEE, appBufferSize); while (p && !bspStringFound) { if (memcmp(p, BSP_SEARCH_STRING, strlen(BSP_SEARCH_STRING)) == 0) { bspStringFound = 1; p1 = strchr(p, COLON) + 1; if (p1 == NULL) { returnVal = 0; goto fail; } for (p2 = bspName; (*p1 != SPACE) && (*p1 != NUL); p1++, p2++) *p2 = *p1; *p2 = NUL; } else { p = memchr(p + 1, TEE, appBufferSize - (p - appBuffer)); } } if (!bspStringFound) returnVal = 0; else printf("%s.%s\n", productName, bspName); } fail: return(returnVal); }