AC_CHECK_FUNCS([sched_yield])
fi
-AC_CHECK_HEADER([lz4.h], AC_CHECK_LIB([lz4], [main]))
+AC_CHECK_HEADER([lz4.h], AC_CHECK_LIB([lz4], [LZ4_decompress_safe]))
AC_CHECK_HEADER([snappy.h], AC_CHECK_LIB([snappy], [main]))
AC_CHECK_HEADER([zlib.h], AC_CHECK_LIB([z], [main]))
AC_CHECK_HEADER([lzma.h], AC_CHECK_LIB([lzma], [main]))
// Ensure consistent behavior in the nullptr case
std::unique_ptr<IOBuf> Codec::compress(const IOBuf* data) {
- return !data->empty() ? doCompress(data) : IOBuf::create(0);
+ uint64_t len = data->computeChainDataLength();
+ if (len == 0) {
+ return IOBuf::create(0);
+ } else if (len > maxUncompressedLength()) {
+ throw std::runtime_error("Codec: uncompressed length too large");
+ }
+
+ return doCompress(data);
}
std::unique_ptr<IOBuf> Codec::uncompress(const IOBuf* data,
}
uint64_t Codec::doMaxUncompressedLength() const {
- return std::numeric_limits<uint64_t>::max() - 1;
+ return UNLIMITED_UNCOMPRESSED_LENGTH;
}
namespace {
}
uint64_t LZ4Codec::doMaxUncompressedLength() const {
- // From lz4.h: "Max supported value is ~1.9GB"; I wish we had something
- // more accurate.
- return 1.8 * (uint64_t(1) << 30);
+ return LZ4_MAX_INPUT_SIZE;
}
std::unique_ptr<IOBuf> LZ4Codec::doCompress(const IOBuf* data) {
}
} else {
actualUncompressedLength = uncompressedLength;
- DCHECK_NE(actualUncompressedLength, UNKNOWN_UNCOMPRESSED_LENGTH);
+ if (actualUncompressedLength == UNKNOWN_UNCOMPRESSED_LENGTH ||
+ actualUncompressedLength > maxUncompressedLength()) {
+ throw std::runtime_error("LZ4Codec: invalid uncompressed length");
+ }
}
- auto out = IOBuf::create(actualUncompressedLength);
auto p = cursor.peek();
- int n = LZ4_uncompress(reinterpret_cast<const char*>(p.first),
- reinterpret_cast<char*>(out->writableTail()),
- actualUncompressedLength);
- if (n != p.second) {
+ auto out = IOBuf::create(actualUncompressedLength);
+ int n = LZ4_decompress_safe(reinterpret_cast<const char*>(p.first),
+ reinterpret_cast<char*>(out->writableTail()),
+ p.second,
+ actualUncompressedLength);
+
+ if (n != actualUncompressedLength) {
throw std::runtime_error(to<std::string>(
"LZ4 decompression returned invalid value ", n));
}
* Return the maximum length of data that may be compressed with this codec.
* NO_COMPRESSION and ZLIB support arbitrary lengths;
* LZ4 supports up to 1.9GiB; SNAPPY supports up to 4GiB.
+ * May return UNLIMITED_UNCOMPRESSED_LENGTH if unlimited.
*/
uint64_t maxUncompressedLength() const;
* an empty IOBuf chain will return an empty IOBuf chain.
*/
static constexpr uint64_t UNKNOWN_UNCOMPRESSED_LENGTH = uint64_t(-1);
+ static constexpr uint64_t UNLIMITED_UNCOMPRESSED_LENGTH = uint64_t(-2);
std::unique_ptr<IOBuf> uncompress(
const IOBuf* data,