summaryrefslogtreecommitdiffstats
path: root/src/corelib
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2021-04-06 14:12:03 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-04-07 19:38:45 +0000
commit51812618e7f0486ad029f3c17bfe7baec8800d06 (patch)
tree43ccce45f1ba20247afeb415bd55e9934f4ac535 /src/corelib
parentae7aabd1b7ac9d13c2c0e8e49b94b90376257e23 (diff)
Avoid attempting to parse insanely long texts as zone names
There are limits on zone name length and the trial-and-error approach we're more or less forced to take to parsing gets horribly expensive if applied to every prefix of a very long string. So apply a loosened version of the zone-name validity rule that limits the length of the fragments between slashes and limit the number of such fragments. Fixes: QTBUG-92275 Change-Id: I83052b1b6888728c81135db22a9c6298ae439375 Reviewed-by: Robert Löhning <robert.loehning@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit 0c9fc20e7ff7b4ff0f15e0b2c071ea834625dce9) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/corelib')
-rw-r--r--src/corelib/time/qdatetimeparser.cpp18
1 files changed, 18 insertions, 0 deletions
diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp
index c64f622a57..0a8721a2b5 100644
--- a/src/corelib/time/qdatetimeparser.cpp
+++ b/src/corelib/time/qdatetimeparser.cpp
@@ -1737,6 +1737,24 @@ QDateTimeParser::findTimeZoneName(QStringView str, const QDateTime &when) const
int index = std::distance(str.cbegin(),
std::find_if(str.cbegin(), str.cend(), invalidZoneNameCharacter));
+ // Limit name fragments (between slashes) to 20 characters.
+ // (Valid time-zone IDs are allowed up to 14 and Android has quirks up to 17.)
+ // Limit number of fragments to six; no known zone name has more than four.
+ int lastSlash = -1;
+ int count = 0;
+ Q_ASSERT(index <= str.size());
+ while (lastSlash < index) {
+ int slash = str.indexOf(QLatin1Char('/'), lastSlash + 1);
+ if (slash < 0)
+ slash = index; // i.e. the end of the candidate text
+ else if (++count > 5)
+ index = slash; // Truncate
+ if (slash - lastSlash > 20)
+ index = lastSlash + 20; // Truncate
+ // If any of those conditions was met, index <= slash, so this exits the loop:
+ lastSlash = slash;
+ }
+
for (; index > systemLength; --index) { // Find longest match
str.truncate(index);
QTimeZone zone(str.toLatin1());