From 48959f7e5b670396805d4d62a44dd4fefac91611 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 7 Apr 2025 21:06:49 +0200 Subject: [PATCH] QStringConverter: widen nameForEncoding()'s contract Coverity apparently mixes bootstrap and non-bootstrap builds: it complains that Encoding::Latin1 indexes encodingInterfaces[] out-of-range (apparently taking the size of the latter from a bootstrapped and the value of the former from a non-bootstrap build). That should somehow be fixed in the Coverity configuration, but it highlighted the fact that we have a narrow-contract function in this security-critical class that can trivially have a wide contract, so widen the contract by returning nullptr for invalid Encoding values. Consequently, mark the function as noexcept. As a drive-by, mark it also as Q_DECL_PURE_FUNCTION. [ChangeLog][QtCore][QStringConverter] The nameForEncoding() function now returns nullptr for an invalid Encoding value. Before, such a call resulted in undefined behavior. Pick-to: 6.9 6.8 6.5 Coverity-Id: 480251 Change-Id: Ie1c5c9df6881147a1ff44fe549e50748b2f5b7da Reviewed-by: Thiago Macieira --- src/corelib/text/qstringconverter.cpp | 14 +++++++++++--- src/corelib/text/qstringconverter_base.h | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/corelib/text/qstringconverter.cpp b/src/corelib/text/qstringconverter.cpp index 1c51cf80c20..b17432c067a 100644 --- a/src/corelib/text/qstringconverter.cpp +++ b/src/corelib/text/qstringconverter.cpp @@ -2710,11 +2710,19 @@ QStringDecoder QStringDecoder::decoderForHtml(QByteArrayView data) #endif // !QT_BOOTSTRAPPED /*! - Returns the canonical name for encoding \a e. + Returns the canonical name for encoding \a e or \nullptr if \a e is an + invalid value. + + \note In Qt versions prior to 6.10, 6.9.1, 6.8.4 or 6.5.9, calling this + function with an invalid argument resulted in undefined behavior. Since the + above-mentioned Qt versions, it returns nullptr instead. */ -const char *QStringConverter::nameForEncoding(QStringConverter::Encoding e) +const char *QStringConverter::nameForEncoding(QStringConverter::Encoding e) noexcept { - return encodingInterfaces[int(e)].name; + auto i = size_t(e); + if (Q_UNLIKELY(i >= std::size(encodingInterfaces))) + return nullptr; + return encodingInterfaces[i].name; } /*! diff --git a/src/corelib/text/qstringconverter_base.h b/src/corelib/text/qstringconverter_base.h index 383eaa8a869..26ea9dfe0d7 100644 --- a/src/corelib/text/qstringconverter_base.h +++ b/src/corelib/text/qstringconverter_base.h @@ -162,7 +162,7 @@ public: Q_CORE_EXPORT static std::optional encodingForName(const char *name) noexcept; #endif Q_CORE_EXPORT static std::optional encodingForName(QAnyStringView name) noexcept; - Q_CORE_EXPORT static const char *nameForEncoding(Encoding e); + Q_DECL_PURE_FUNCTION Q_CORE_EXPORT static const char *nameForEncoding(Encoding e) noexcept; Q_CORE_EXPORT static std::optional encodingForData(QByteArrayView data, char16_t expectedFirstCharacter = 0) noexcept; Q_CORE_EXPORT static std::optional encodingForHtml(QByteArrayView data);