From 0c9fc20e7ff7b4ff0f15e0b2c071ea834625dce9 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 6 Apr 2021 14:12:03 +0200 Subject: [PATCH 1/2] Avoid attempting to parse insanely long texts as zone names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Pick-to: 6.1 6.0 5.15 Change-Id: I83052b1b6888728c81135db22a9c6298ae439375 Reviewed-by: Robert Löhning Reviewed-by: Thiago Macieira --- src/corelib/time/qdatetimeparser.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/corelib/time/qdatetimeparser.cpp b/src/corelib/time/qdatetimeparser.cpp index d85a904450..2a16adedbf 100644 --- a/src/corelib/time/qdatetimeparser.cpp +++ b/src/corelib/time/qdatetimeparser.cpp @@ -1740,6 +1740,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()); From a4d1ed854d14f3f15218f6c9bc2ff190259a4d5a Mon Sep 17 00:00:00 2001 From: Sona Kurazyan Date: Wed, 7 Apr 2021 13:41:17 +0200 Subject: [PATCH 2/2] Do not notify about property changes if the value hasn't changed After 2ffb91ac592d69adf9458ac45074174537435918 we manually call notify() for QObjectCompatProperties. Currently we always call it when setting values to compat properties, even if the value hasn't actually changed. Fixed to call notify() only if the value is being changed. Task-number: QTBUG-85520 Change-Id: I385db84c4009c45406e204b96e0e37ce5fa8882b Reviewed-by: Andreas Buhr Reviewed-by: Fabian Kosmale --- src/corelib/animation/qpauseanimation.cpp | 9 +++++++-- src/corelib/kernel/qtimer.cpp | 8 ++++++-- src/gui/image/qmovie.cpp | 8 ++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/corelib/animation/qpauseanimation.cpp b/src/corelib/animation/qpauseanimation.cpp index c2599da692..04d8cca273 100644 --- a/src/corelib/animation/qpauseanimation.cpp +++ b/src/corelib/animation/qpauseanimation.cpp @@ -129,8 +129,13 @@ void QPauseAnimation::setDuration(int msecs) return; } Q_D(QPauseAnimation); - d->duration.setValue(msecs); - d->duration.notify(); + + if (msecs != d->duration) { + d->duration = msecs; + d->duration.notify(); + } else { + d->duration.removeBindingUnlessInWrapper(); + } } QBindable QPauseAnimation::bindableDuration() diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp index 0946e1af48..333e6c24ba 100644 --- a/src/corelib/kernel/qtimer.cpp +++ b/src/corelib/kernel/qtimer.cpp @@ -257,9 +257,11 @@ void QTimer::start() void QTimer::start(int msec) { Q_D(QTimer); + const bool intervalChanged = msec != d->inter; d->inter.setValue(msec); start(); - d->inter.notify(); + if (intervalChanged) + d->inter.notify(); } @@ -753,6 +755,7 @@ QBindable QTimer::bindableSingleShot() void QTimer::setInterval(int msec) { Q_D(QTimer); + const bool intervalChanged = msec != d->inter; d->inter.setValue(msec); if (d->id != INV_TIMER) { // create new timer QObject::killTimer(d->id); // restart timer @@ -761,7 +764,8 @@ void QTimer::setInterval(int msec) // as timer state actually does not change } - d->inter.markDirty(); + if (intervalChanged) + d->inter.markDirty(); } int QTimer::interval() const diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp index a293d358cf..b00d3ff25c 100644 --- a/src/gui/image/qmovie.cpp +++ b/src/gui/image/qmovie.cpp @@ -929,8 +929,12 @@ void QMovie::setSpeed(int percentSpeed) Q_D(QMovie); if (!d->speed && d->movieState == Running) d->nextImageTimer.start(nextFrameDelay()); - d->speed.setValue(percentSpeed); - d->speed.notify(); + if (percentSpeed != d->speed) { + d->speed = percentSpeed; + d->speed.notify(); + } else { + d->speed.removeBindingUnlessInWrapper(); + } } int QMovie::speed() const