diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2024-01-08 14:47:12 -0300 |
---|---|---|
committer | Marc Mutz <marc.mutz@qt.io> | 2024-01-11 00:37:29 +0000 |
commit | d351a97e85e5ed8acd7ad1357ef76dc2e0ad639f (patch) | |
tree | 2be2c985faacb3a7db09a64e16861f519bc88c5a | |
parent | 44b7b1d11b7c83b1f19df915577224f97371c655 (diff) |
QString::arg: don't pass nullptr to memcpy()
A null QString / QStringView has a null begin pointer stored as its
array beginning (something we hide a little in the QString::data()
function, but not in QStringView::data()). We've been passing a null
pointer to memcpy() every time someone passed a null QStringView for
QString's single-argument arg() call, though not the multi-string arg()
version (which is the only one QStringView offers).
Commit f5021835dfb4b0bf974794b598cbdf9f0f95898d made this worse by
making QStringViews created from null QStrings retain the nullness (as
was intended).
Fixes: QTBUG-120624
Pick-to: 6.2 6.5 6.6 6.7
Change-Id: I6e2677aad2ab45759db2fffd17a870639b19340b
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
-rw-r--r-- | src/corelib/text/qstring.cpp | 3 | ||||
-rw-r--r-- | tests/auto/corelib/text/qstring/tst_qstring.cpp | 19 | ||||
-rw-r--r-- | tests/auto/corelib/text/qstringview/tst_qstringview.cpp | 4 |
3 files changed, 23 insertions, 3 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index 4c2bef298f..6b06f1581e 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -8405,7 +8405,8 @@ static QString replaceArgEscapes(QStringView s, const ArgEscapeData &d, qsizetyp rc = std::fill_n(rc, pad_chars, fillChar); } - memcpy(rc, use.data(), use.size() * sizeof(QChar)); + if (use.size()) + memcpy(rc, use.data(), use.size() * sizeof(QChar)); rc += use.size(); if (field_width < 0) { // right padded diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index b31c5dedb8..48e64986d1 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -6558,9 +6558,18 @@ void tst_QString::arg() QString s13(u"%1% %x%c%2 %d%2-%"_s); QString s14(u"%1%2%3"_s); + const QString null; + const QString empty(u""_s); const QString foo(u"foo"_s); const QString bar(u"bar"_s); + Q_ASSERT(null.isNull()); + Q_ASSERT(!empty.isNull()); + QCOMPARE(s4.arg(null), "[]"_L1); + QCOMPARE(s4.arg(empty), "[]"_L1); + QCOMPARE(s4.arg(QStringView()), "[]"_L1); + QCOMPARE(s4.arg(QStringView(u"")), "[]"_L1); + QCOMPARE(s4.arg(foo), "[foo]"_L1); QCOMPARE( s5.arg(QLatin1String("foo")), QLatin1String("[foo]") ); QCOMPARE( s6.arg(u"foo"), QLatin1String("[foo]") ); @@ -6653,6 +6662,14 @@ void tst_QString::arg() QCOMPARE(QString(u"%%%"_s).arg(0), "%%%"_L1); QCOMPARE(QString(u"%%%1%%%2"_s).arg(foo).arg(bar), "%%foo%%bar"_L1); + QCOMPARE(u"%1"_s.arg(null, 3), " "_L1); + QCOMPARE(u"%1"_s.arg(empty, 3), " "_L1); + QCOMPARE(u"%1"_s.arg(QStringView(), 3), " "_L1); + QCOMPARE(u"%1"_s.arg(QStringView(u""), 3), " "_L1); + QCOMPARE(u"%1%1"_s.arg(null), ""_L1); + QCOMPARE(u"%2%1"_s.arg(empty), "%2"_L1); + QCOMPARE(u"%2%1"_s.arg(QStringView()), "%2"_L1); + QCOMPARE(u"%2%1"_s.arg(QStringView(u"")), "%2"_L1); QCOMPARE(u"%1"_s.arg(u"hello"_s, -10), "hello "_L1); QCOMPARE(u"%1"_s.arg("hello"_L1, -5), "hello"_L1); QCOMPARE(u"%1"_s.arg(u"hello", -2), "hello"_L1); @@ -6662,8 +6679,6 @@ void tst_QString::arg() QCOMPARE(u"%1"_s.arg(u"hello"_s, 10), " hello"_L1); QCOMPARE(u"%1%1"_s.arg(u"hello"_s), "hellohello"_L1); QCOMPARE(u"%2%1"_s.arg(u"hello"_s), "%2hello"_L1); - QCOMPARE(u"%1%1"_s.arg(QString()), QLatin1String("")); - QCOMPARE(u"%2%1"_s.arg(u""_s), "%2"_L1); QCOMPARE( QString(u"%2 %L1"_s).arg(12345.6789).arg(12345.6789), QLatin1String("12345.7 12.345,7") ); diff --git a/tests/auto/corelib/text/qstringview/tst_qstringview.cpp b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp index e0564ac671..5adb8d5213 100644 --- a/tests/auto/corelib/text/qstringview/tst_qstringview.cpp +++ b/tests/auto/corelib/text/qstringview/tst_qstringview.cpp @@ -469,6 +469,10 @@ void tst_QStringView::at() const void tst_QStringView::arg() const { + // nullness checks + QCOMPARE(QStringView().arg(QStringView()), ""); + QCOMPARE(QStringView("%1").arg(QStringView()), ""); + #define CHECK1(pattern, arg1, expected) \ do { \ auto p = QStringView(u"" pattern); \ |