diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2021-06-18 09:48:55 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2021-06-22 22:08:16 +0200 |
commit | e99e07cb5c939ca5bbb1dfdeb66c862d6cd4f2f2 (patch) | |
tree | 9eb1412c71fd8109528d53448a9dd53dbc7eb23e | |
parent | 9cc7f233c9e2f2bacdcb06f166d0812d58eb4bfc (diff) |
QString: Respect precision when reading data for %.*s format string
If we disregard the precision we may read a very large string that we
subsequently discard. Furthermore, people use this to read
non-null-terminated strings, which randomly crashes.
Pick-to: 5.15 6.1 6.2
Change-Id: Ifa255dbe71c82d3d4fb46adfef7a9dc74bd40cee
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/text/qstring.cpp | 12 | ||||
-rw-r--r-- | tests/auto/corelib/text/qstring/tst_qstring.cpp | 30 |
2 files changed, 38 insertions, 4 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp index a8f0c0b142..c98e4ba6d9 100644 --- a/src/corelib/text/qstring.cpp +++ b/src/corelib/text/qstring.cpp @@ -6774,13 +6774,17 @@ QString QString::vasprintf(const char *cformat, va_list ap) if (length_mod == lm_l) { const ushort *buff = va_arg(ap, const ushort*); const ushort *ch = buff; - while (*ch != 0) + while (precision != 0 && *ch != 0) { ++ch; + --precision; + } subst.setUtf16(buff, ch - buff); - } else + } else if (precision == -1) { subst = QString::fromUtf8(va_arg(ap, const char*)); - if (precision != -1) - subst.truncate(precision); + } else { + const char *buff = va_arg(ap, const char*); + subst = QString::fromUtf8(buff, qstrnlen(buff, precision)); + } ++c; break; } diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index c9fbff67c3..26d10244ae 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -594,6 +594,7 @@ private slots: void isValidUtf16_data(); void isValidUtf16(); void unicodeStrings(); + void vasprintfWithPrecision(); }; template <class T> const T &verifyZeroTermination(const T &t) { return t; } @@ -7088,6 +7089,35 @@ void tst_QString::isValidUtf16() QTEST(string.isValidUtf16(), "valid"); } +static QString doVasprintf(const char *msg, ...) { + va_list args; + va_start(args, msg); + const QString result = QString::vasprintf(msg, args); + va_end(args); + return result; +} + +void tst_QString::vasprintfWithPrecision() +{ + { + const char *msg = "Endpoint %.*s with"; + static const char arg0[3] = { 'a', 'b', 'c' }; + static const char arg1[4] = { 'a', 'b', 'c', '\0' }; + QCOMPARE(doVasprintf(msg, 3, arg0), QStringLiteral("Endpoint abc with")); + QCOMPARE(doVasprintf(msg, 9, arg1), QStringLiteral("Endpoint abc with")); + QCOMPARE(doVasprintf(msg, 0, nullptr), QStringLiteral("Endpoint with")); + } + + { + const char *msg = "Endpoint %.*ls with"; + static const ushort arg0[3] = { 'a', 'b', 'c' }; + static const ushort arg1[4] = { 'a', 'b', 'c', '\0' }; + QCOMPARE(doVasprintf(msg, 3, arg0), QStringLiteral("Endpoint abc with")); + QCOMPARE(doVasprintf(msg, 9, arg1), QStringLiteral("Endpoint abc with")); + QCOMPARE(doVasprintf(msg, 0, nullptr), QStringLiteral("Endpoint with")); + } +} + // QString's collation order is only supported during the lifetime as QCoreApplication QTEST_GUILESS_MAIN(tst_QString) |