From a54d44298f6d2ecc1ec4d8c5c42c89c8a06fc5dd Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 14 Sep 2016 16:14:16 +0200 Subject: QLatin1String: Fix UB (nullptr passed) in relational operators Found by UBSan: qstring.h:1160:44: runtime error: null pointer passed as argument 1, which is declared to never be null qstring.h:1160:44: runtime error: null pointer passed as argument 2, which is declared to never be null Fix by avoiding the memcmp() calls if there's a chance that they might be called with nullptr. While at it, also implement !=, >, <=, >= in terms of ==, <, and add a test, because this particular UB was not fingered by any of the QtCore test cases, but by a Qt3D one. Change-Id: I413792dcc8431ef14f0c79f26e89a3e9fab69465 Reviewed-by: Thiago Macieira Reviewed-by: Edward Welbourne --- src/corelib/tools/qstring.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/corelib/tools/qstring.h') diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 886973fe10..58ad2caa2b 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1127,21 +1127,21 @@ inline bool operator!=(QString::Null, const QString &s) { return !s.isNull(); } inline bool operator!=(const QString &s, QString::Null) { return !s.isNull(); } inline bool operator==(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ return (s1.size() == s2.size() && !memcmp(s1.latin1(), s2.latin1(), s1.size())); } +{ return s1.size() == s2.size() && (!s1.size() || !memcmp(s1.latin1(), s2.latin1(), s1.size())); } inline bool operator!=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ return (s1.size() != s2.size() || memcmp(s1.latin1(), s2.latin1(), s1.size())); } +{ return !operator==(s1, s2); } inline bool operator<(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size())); - return (r < 0) || (r == 0 && s1.size() < s2.size()); } -inline bool operator<=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size())); - return (r < 0) || (r == 0 && s1.size() <= s2.size()); } +{ + const int len = qMin(s1.size(), s2.size()); + const int r = len ? memcmp(s1.latin1(), s2.latin1(), len) : 0; + return r < 0 || (r == 0 && s1.size() < s2.size()); +} inline bool operator>(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size())); - return (r > 0) || (r == 0 && s1.size() > s2.size()); } +{ return operator<(s2, s1); } +inline bool operator<=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW +{ return !operator>(s1, s2); } inline bool operator>=(QLatin1String s1, QLatin1String s2) Q_DECL_NOTHROW -{ int r = memcmp(s1.latin1(), s2.latin1(), qMin(s1.size(), s2.size())); - return (r > 0) || (r == 0 && s1.size() >= s2.size()); } +{ return !operator<(s1, s2); } inline bool QLatin1String::operator==(const QString &s) const Q_DECL_NOTHROW { return s == *this; } -- cgit v1.2.3 From c59c759fcccd17b06255e7062cc1ceb532912a8a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 15 Sep 2016 09:07:53 -0700 Subject: Suppress ICC warning #111 about unreachable code in toWCharArray qstring.h(961): warning #111: statement is unreachable Change-Id: I33dc971f005a4848bb8ffffd14748ae03dadefc9 Reviewed-by: Marc Mutz --- src/corelib/tools/qstring.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/corelib/tools/qstring.h') diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 58ad2caa2b..4863b1d2c5 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -947,6 +947,7 @@ inline QString QString::section(QChar asep, int astart, int aend, SectionFlags a QT_WARNING_PUSH QT_WARNING_DISABLE_MSVC(4127) // "conditional expression is constant" +QT_WARNING_DISABLE_INTEL(111) // "statement is unreachable" inline int QString::toWCharArray(wchar_t *array) const { -- cgit v1.2.3