summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2024-01-08 14:47:12 -0300
committerMarc Mutz <marc.mutz@qt.io>2024-01-11 00:37:29 +0000
commitd351a97e85e5ed8acd7ad1357ef76dc2e0ad639f (patch)
tree2be2c985faacb3a7db09a64e16861f519bc88c5a
parent44b7b1d11b7c83b1f19df915577224f97371c655 (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.cpp3
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring.cpp19
-rw-r--r--tests/auto/corelib/text/qstringview/tst_qstringview.cpp4
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); \