summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/tools/qlatin1string
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2016-09-14 16:14:16 +0200
committerMarc Mutz <marc.mutz@kdab.com>2016-09-15 10:10:28 +0000
commita54d44298f6d2ecc1ec4d8c5c42c89c8a06fc5dd (patch)
tree3eac6336bdb8c8f86c9cd33098ae09bc46c9541d /tests/auto/corelib/tools/qlatin1string
parent7529c39ba350c3fe9a2b4a96d3300481e3ea419f (diff)
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 <thiago.macieira@intel.com> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'tests/auto/corelib/tools/qlatin1string')
-rw-r--r--tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp57
1 files changed, 57 insertions, 0 deletions
diff --git a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp b/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
index 290c9fc12a..6f16120bd0 100644
--- a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
+++ b/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
@@ -35,6 +35,15 @@
#include <QString>
+// Preserve QLatin1String-ness (QVariant(QLatin1String) creates a QVariant::String):
+struct QLatin1StringContainer {
+ QLatin1String l1;
+};
+QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(QLatin1StringContainer, Q_MOVABLE_TYPE);
+QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QLatin1StringContainer)
+
class tst_QLatin1String : public QObject
{
Q_OBJECT
@@ -42,6 +51,8 @@ class tst_QLatin1String : public QObject
private Q_SLOTS:
void nullString();
void emptyString();
+ void relationalOperators_data();
+ void relationalOperators();
};
void tst_QLatin1String::nullString()
@@ -119,7 +130,53 @@ void tst_QLatin1String::emptyString()
}
}
+void tst_QLatin1String::relationalOperators_data()
+{
+ QTest::addColumn<QLatin1StringContainer>("lhs");
+ QTest::addColumn<int>("lhsOrderNumber");
+ QTest::addColumn<QLatin1StringContainer>("rhs");
+ QTest::addColumn<int>("rhsOrderNumber");
+ struct Data {
+ QLatin1String l1;
+ int order;
+ } data[] = {
+ { QLatin1String(), 0 },
+ { QLatin1String(""), 0 },
+ { QLatin1String("a"), 1 },
+ { QLatin1String("aa"), 2 },
+ { QLatin1String("b"), 3 },
+ };
+
+ for (Data *lhs = data; lhs != data + sizeof data / sizeof *data; ++lhs) {
+ for (Data *rhs = data; rhs != data + sizeof data / sizeof *data; ++rhs) {
+ QLatin1StringContainer l = { lhs->l1 }, r = { rhs->l1 };
+ QTest::newRow(qPrintable(QString::asprintf("\"%s\" <> \"%s\"",
+ lhs->l1.data() ? lhs->l1.data() : "nullptr",
+ rhs->l1.data() ? rhs->l1.data() : "nullptr")))
+ << l << lhs->order << r << rhs->order;
+ }
+ }
+}
+
+void tst_QLatin1String::relationalOperators()
+{
+ QFETCH(QLatin1StringContainer, lhs);
+ QFETCH(int, lhsOrderNumber);
+ QFETCH(QLatin1StringContainer, rhs);
+ QFETCH(int, rhsOrderNumber);
+
+#define CHECK(op) \
+ QCOMPARE(lhs.l1 op rhs.l1, lhsOrderNumber op rhsOrderNumber) \
+ /*end*/
+ CHECK(==);
+ CHECK(!=);
+ CHECK(< );
+ CHECK(> );
+ CHECK(<=);
+ CHECK(>=);
+#undef CHECK
+}
QTEST_APPLESS_MAIN(tst_QLatin1String)