summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-06-18 09:48:55 +0200
committerUlf Hermann <ulf.hermann@qt.io>2021-06-23 21:29:15 +0200
commita93cf5835d87ecb7c850a494847f5bde863cae22 (patch)
tree3087ce00006dc70dd57e1b7b1613a25ee4cf070b
parent53d9c8d761eb6ff8637a0758b45a77ae3b68df05 (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. Change-Id: Ifa255dbe71c82d3d4fb46adfef7a9dc74bd40cee Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit e99e07cb5c939ca5bbb1dfdeb66c862d6cd4f2f2) Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/corelib/text/qstring.cpp12
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring.cpp30
2 files changed, 38 insertions, 4 deletions
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index db6c1487c8..d51916d31a 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -6770,13 +6770,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 963ab2aa1a..0553adcf2a 100644
--- a/tests/auto/corelib/text/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp
@@ -583,6 +583,7 @@ private slots:
void isValidUtf16_data();
void isValidUtf16();
void unicodeStrings();
+ void vasprintfWithPrecision();
};
template <class T> const T &verifyZeroTermination(const T &t) { return t; }
@@ -6956,6 +6957,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"));
+ }
+}
+
QTEST_APPLESS_MAIN(tst_QString)
#include "tst_qstring.moc"