From 91176c3fee41a9365f32f18f3fecc3473795c386 Mon Sep 17 00:00:00 2001 From: Rex Dieter Date: Mon, 12 Dec 2016 06:41:27 -0600 Subject: [PATCH] 5.7.0-6 - Backported QTBUG-53071 patch to resolve problem with latest tzdata. - Fixed Source URL. --- qt5-qtbase.spec | 12 +- qtbase-opensource-src-5.7.0-QTBUG-53071.patch | 272 ++++++++++++++++++ 2 files changed, 282 insertions(+), 2 deletions(-) create mode 100644 qtbase-opensource-src-5.7.0-QTBUG-53071.patch diff --git a/qt5-qtbase.spec b/qt5-qtbase.spec index d1d7565..3933dee 100644 --- a/qt5-qtbase.spec +++ b/qt5-qtbase.spec @@ -62,12 +62,12 @@ BuildRequires: pkgconfig(libsystemd) Name: qt5-qtbase Summary: Qt5 - QtBase components Version: 5.7.0 -Release: 5%{?dist} +Release: 6%{?dist} # See LGPL_EXCEPTIONS.txt, for exception details License: LGPLv2 with exceptions or GPLv3 with exceptions Url: http://qt-project.org/ -Source0: http://download.qt.io/official_releases/qt/5.6/%{version}%{?prerelease:-%{prerelease}}/submodules/%{qt_module}-opensource-src-%{version}%{?prerelease:-%{prerelease}}.tar.xz +Source0: http://download.qt.io/official_releases/qt/5.7/%{version}%{?prerelease:-%{prerelease}}/submodules/%{qt_module}-opensource-src-%{version}%{?prerelease:-%{prerelease}}.tar.xz # https://bugzilla.redhat.com/show_bug.cgi?id=1227295 Source1: qtlogging.ini @@ -89,6 +89,9 @@ Patch2: qtbase-multilib_optflags.patch # fix QTBUG-35459 (too low entityCharacterLimit=1024 for CVE-2013-4549) Patch4: qtbase-opensource-src-5.3.2-QTBUG-35459.patch +# fix QTBUG-53071 (backport for Qt 5.7.0. Already in upstream since 5.7.1). +Patch5: qtbase-opensource-src-5.7.0-QTBUG-53071.patch + # unconditionally enable freetype lcdfilter support Patch12: qtbase-opensource-src-5.2.0-enable_ft_lcdfilter.patch @@ -333,6 +336,7 @@ Qt5 libraries used for drawing widgets and OpenGL items. %setup -q -n %{qt_module}-opensource-src-%{version}%{?prerelease:-%{prerelease}} %patch4 -p1 -b .QTBUG-35459 +%patch5 -p1 -b .QTBUG-53071 %patch12 -p1 -b .enable_ft_lcdfilter %patch52 -p1 -b .moc_WORDSIZE @@ -931,6 +935,10 @@ fi %changelog +* Mon Dec 12 2016 Vitaly Zaitsev - 5.7.0-6 +- Backported QTBUG-53071 patch to resolve problem with latest tzdata. +- Fixed Source URL. + * Fri Dec 09 2016 Rex Dieter - 5.7.0-5 - restore moc_system_defines.patch lost in 5.7.0 rebase diff --git a/qtbase-opensource-src-5.7.0-QTBUG-53071.patch b/qtbase-opensource-src-5.7.0-QTBUG-53071.patch new file mode 100644 index 0000000..a348cda --- /dev/null +++ b/qtbase-opensource-src-5.7.0-QTBUG-53071.patch @@ -0,0 +1,272 @@ +From e9041c7fc1052167f1ec2df0ea9623059e55d00f Mon Sep 17 00:00:00 2001 +From: Thiago Macieira +Date: Thu, 28 Apr 2016 22:09:01 -0700 +Subject: [PATCH] Fix parsing of tzfile(5) POSIX rule zone names with bracket + quotes + +POSIX.1-2001 allows quoting a zone name so that it can contain other +characters besides letters, by enclosing it in angle brackets ('<' and +'>'). This hadn't been used until recently (tzdata2016b), when the +Asia/Barnaul rule started using a zone name "+07" (the name variable +contained the value "<+07>-7"). + +Thanks to Paul Eggert for reporting and investigating the root cause. + +Task-number: QTBUG-53071 +Change-Id: Id5480807d25e49e78b79ffff1449bc410776cb66 +Reviewed-by: Edward Welbourne +Reviewed-by: Lars Knoll +--- + src/corelib/tools/qtimezoneprivate_tz.cpp | 176 ++++++++++++++------- + .../auto/corelib/tools/qtimezone/tst_qtimezone.cpp | 10 ++ + 2 files changed, 130 insertions(+), 56 deletions(-) + +diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp +index 85ed345..cb9581a 100644 +--- a/src/corelib/tools/qtimezoneprivate_tz.cpp ++++ b/src/corelib/tools/qtimezoneprivate_tz.cpp +@@ -41,6 +41,8 @@ + + #include + ++#include "qlocale_tools_p.h" ++ + #include + + QT_BEGIN_NAMESPACE +@@ -384,25 +386,100 @@ static QTime parsePosixTime(const QByteArray &timeRule) + return QTime(2, 0, 0); + } + +-static int parsePosixOffset(const QByteArray &timeRule) ++static int parsePosixOffset(const char *begin, const char *end) + { + // Format "[+|-]hh[:mm[:ss]]" +- QList parts = timeRule.split(':'); +- int count = parts.count(); +- if (count == 3) { +- int hour = parts.at(0).toInt(); +- int sign = hour >= 0 ? -1 : 1; +- return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60) + parts.at(2).toInt()); +- } else if (count == 2) { +- int hour = parts.at(0).toInt(); +- int sign = hour >= 0 ? -1 : 1; +- return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60)); +- } else if (count == 1) { +- int hour = parts.at(0).toInt(); +- int sign = hour >= 0 ? -1 : 1; +- return sign * (qAbs(hour) * 60 * 60); +- } +- return 0; ++ int hour, min = 0, sec = 0; ++ ++ // note that the sign is inverted because POSIX counts in hours West of GMT ++ bool negate = true; ++ if (*begin == '+') { ++ ++begin; ++ } else if (*begin == '-') { ++ negate = false; ++ ++begin; ++ } ++ ++ bool ok = false; ++ hour = qstrtoll(begin, &begin, 10, &ok); ++ if (!ok) ++ return INT_MIN; ++ if (begin < end && *begin == ':') { ++ // minutes ++ ++begin; ++ min = qstrtoll(begin, &begin, 10, &ok); ++ if (!ok || min < 0) ++ return INT_MIN; ++ ++ if (begin < end && *begin == ':') { ++ // seconds ++ ++begin; ++ sec = qstrtoll(begin, &begin, 10, &ok); ++ if (!ok || sec < 0) ++ return INT_MIN; ++ } ++ } ++ ++ // we must have consumed everything ++ if (begin != end) ++ return INT_MIN; ++ ++ int value = (hour * 60 + min) * 60 + sec; ++ return negate ? -value : value; ++} ++ ++static inline bool asciiIsLetter(char ch) ++{ ++ ch |= 0x20; // lowercases if it is a letter, otherwise just corrupts ch ++ return ch >= 'a' && ch <= 'z'; ++} ++ ++// Returns the zone name, the offset (in seconds) and advances \a begin to ++// where the parsing ended. Returns a zone of INT_MIN in case an offset ++// couldn't be read. ++static QPair parsePosixZoneNameAndOffset(const char *&pos, const char *end) ++{ ++ static const char offsetChars[] = "0123456789:"; ++ QPair result = qMakePair(QString(), INT_MIN); ++ ++ const char *nameBegin = pos; ++ const char *nameEnd; ++ Q_ASSERT(pos < end); ++ ++ if (*pos == '<') { ++ nameBegin = pos + 1; // skip the '<' ++ nameEnd = nameBegin; ++ while (nameEnd < end && *nameEnd != '>') { ++ // POSIX says only alphanumeric, but we allow anything ++ ++nameEnd; ++ } ++ pos = nameEnd + 1; // skip the '>' ++ } else { ++ nameBegin = pos; ++ nameEnd = nameBegin; ++ while (nameEnd < end && asciiIsLetter(*nameEnd)) ++ ++nameEnd; ++ pos = nameEnd; ++ } ++ if (nameEnd - nameBegin < 3) ++ return result; // name must be at least 3 characters long ++ ++ // zone offset, form [+-]hh:mm:ss ++ const char *zoneBegin = pos; ++ const char *zoneEnd = pos; ++ if (zoneEnd < end && (zoneEnd[0] == '+' || zoneEnd[0] == '-')) ++ ++zoneEnd; ++ while (zoneEnd < end) { ++ if (strchr(offsetChars, char(*zoneEnd)) == NULL) ++ break; ++ ++zoneEnd; ++ } ++ ++ result.first = QString::fromUtf8(nameBegin, nameEnd - nameBegin); ++ if (zoneEnd > zoneBegin) ++ result.second = parsePosixOffset(zoneBegin, zoneEnd); ++ pos = zoneEnd; ++ return result; + } + + static QVector calculatePosixTransitions(const QByteArray &posixRule, +@@ -419,51 +496,38 @@ static QVector calculatePosixTransitions(const QByteArra + + // POSIX Format is like "TZ=CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00" + // i.e. "std offset dst [offset],start[/time],end[/time]" +- // See http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html ++ // See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html + QList parts = posixRule.split(','); + +- QString name = QString::fromUtf8(parts.at(0)); +- QString stdName; +- QString stdOffsetString; +- QString dstName; +- QString dstOffsetString; +- bool parsedStdName = false; +- bool parsedStdOffset = false; +- for (int i = 0; i < name.size(); ++i) { +- if (name.at(i).isLetter()) { +- if (parsedStdName) { +- parsedStdOffset = true; +- dstName.append(name.at(i)); +- } else { +- stdName.append(name.at(i)); ++ QPair stdZone, dstZone; ++ { ++ const QByteArray &zoneinfo = parts.at(0); ++ const char *begin = zoneinfo.constBegin(); ++ ++ stdZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd()); ++ if (stdZone.second == INT_MIN) { ++ stdZone.second = 0; // reset to UTC if we failed to parse ++ } else if (begin < zoneinfo.constEnd()) { ++ dstZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd()); ++ if (dstZone.second == INT_MIN) { ++ // if the dst offset isn't provided, it is 1 hour ahead of the standard offset ++ dstZone.second = stdZone.second + (60 * 60); + } +- } else { +- parsedStdName = true; +- if (parsedStdOffset) +- dstOffsetString.append(name.at(i)); +- else +- stdOffsetString.append(name.at(i)); + } + } + +- int utcOffset = parsePosixOffset(stdOffsetString.toUtf8()); +- + // If only the name part then no transitions + if (parts.count() == 1) { + QTimeZonePrivate::Data data; + data.atMSecsSinceEpoch = lastTranMSecs; +- data.offsetFromUtc = utcOffset; +- data.standardTimeOffset = utcOffset; ++ data.offsetFromUtc = stdZone.second; ++ data.standardTimeOffset = stdZone.second; + data.daylightTimeOffset = 0; +- data.abbreviation = stdName; ++ data.abbreviation = stdZone.first; + result << data; + return result; + } + +- // If not populated the total dst offset is 1 hour +- int dstOffset = utcOffset + (60 * 60); +- if (!dstOffsetString.isEmpty()) +- dstOffset = parsePosixOffset(dstOffsetString.toUtf8()); + + // Get the std to dst transtion details + QList dstParts = parts.at(1).split('/'); +@@ -486,18 +550,18 @@ static QVector calculatePosixTransitions(const QByteArra + for (int year = startYear; year <= endYear; ++year) { + QTimeZonePrivate::Data dstData; + QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC); +- dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (utcOffset * 1000); +- dstData.offsetFromUtc = dstOffset; +- dstData.standardTimeOffset = utcOffset; +- dstData.daylightTimeOffset = dstOffset - utcOffset; +- dstData.abbreviation = dstName; ++ dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.second * 1000); ++ dstData.offsetFromUtc = dstZone.second; ++ dstData.standardTimeOffset = stdZone.second; ++ dstData.daylightTimeOffset = dstZone.second - stdZone.second; ++ dstData.abbreviation = dstZone.first; + QTimeZonePrivate::Data stdData; + QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC); +- stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstOffset * 1000); +- stdData.offsetFromUtc = utcOffset; +- stdData.standardTimeOffset = utcOffset; ++ stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.second * 1000); ++ stdData.offsetFromUtc = stdZone.second; ++ stdData.standardTimeOffset = stdZone.second; + stdData.daylightTimeOffset = 0; +- stdData.abbreviation = stdName; ++ stdData.abbreviation = stdZone.first; + // Part of the high year will overflow + if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) { + if (dstData.atMSecsSinceEpoch > 0) { +diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp +index ea83510..ce72e7c 100644 +--- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp ++++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp +@@ -847,6 +847,16 @@ void tst_QTimeZone::tzTest() + QTzTimeZonePrivate::Data datatz2 = tztz2.data(std); + QTzTimeZonePrivate::Data datautc2 = tzutc2.data(std); + QCOMPARE(datatz2.offsetFromUtc, datautc2.offsetFromUtc); ++ ++ // Test a timezone with a name that isn't all letters ++ QTzTimeZonePrivate tzBarnaul("Asia/Barnaul"); ++ if (tzBarnaul.isValid()) { ++ QCOMPARE(tzBarnaul.data(std).abbreviation, QString("+07")); ++ ++ // first full day of the new rule (tzdata2016b) ++ QDateTime dt(QDate(2016, 3, 28), QTime(0, 0, 0), Qt::UTC); ++ QCOMPARE(tzBarnaul.data(dt.toMSecsSinceEpoch()).abbreviation, QString("+07")); ++ } + #endif // Q_OS_UNIX + } +