diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index 7c65b67b7ac..8e08615ab37 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -314,6 +314,36 @@ template bool mul_overflow(T v1, T *r) } #endif // Q_CLANG_QDOC +/* + Safely narrows \a x to \c{To}. Let \c L be + \c{std::numeric_limit::min()} and \c H be \c{std::numeric_limit::max()}. + + If \a x is less than L, returns L. If \a x is greater than H, + returns H. Otherwise, returns \c{To(x)}. +*/ +template +static auto qt_saturate(From x) +{ + static_assert(std::is_integral_v); + static_assert(std::is_integral_v); + + [[maybe_unused]] + constexpr auto Lo = (std::numeric_limits::min)(); + constexpr auto Hi = (std::numeric_limits::max)(); + + if constexpr (std::is_signed_v == std::is_signed_v) { + return x < Lo ? Lo : + x > Hi ? Hi : + /*else*/ To(x); + } else { + if constexpr (std::is_signed_v) { // ie. !is_signed_v + if (x < From{0}) + return To{0}; + } + return x > Hi ? Hi : To(x); + } +} + QT_END_NAMESPACE #endif // QNUMERIC_P_H diff --git a/src/corelib/text/qbytearray.cpp b/src/corelib/text/qbytearray.cpp index 0544972213d..9e229b9e835 100644 --- a/src/corelib/text/qbytearray.cpp +++ b/src/corelib/text/qbytearray.cpp @@ -603,7 +603,7 @@ QByteArray qCompress(const uchar* data, qsizetype nbytes, int compressionLevel) switch (res) { case Z_OK: bazip.resize(len + HeaderSize); - qToBigEndian(CompressSizeHint_t(nbytes), bazip.data()); + qToBigEndian(qt_saturate(nbytes), bazip.data()); break; case Z_MEM_ERROR: return tooMuchData(ZLibOp::Compression);