From 845eabb3145982320dce205ebd5bb034e66dfbc8 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 23 Mar 2022 14:25:09 +0100 Subject: Fix ICU's handling of last representable transition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ICU's search for next transition, when the result would lie later than is representable by qint64, returns the last transition before the bound, even if this is at the time it was meant to exclude from the range searched. This lead to infinite looping when we tried to traverse transitions forward. Recognize when this happens and return the invalid data object that indicates falling off the end of time instead. Task-number: QTBUG-99747 Pick-to: 6.3 6.2 Change-Id: I1a210fb7a4086b2fdb052b2260c800bfc29f965a Reviewed-by: MÃ¥rten Nordheim --- src/corelib/time/qtimezoneprivate_icu.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/corelib/time/qtimezoneprivate_icu.cpp b/src/corelib/time/qtimezoneprivate_icu.cpp index 798f231219..b1de236fcb 100644 --- a/src/corelib/time/qtimezoneprivate_icu.cpp +++ b/src/corelib/time/qtimezoneprivate_icu.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 John Layt -** Copyright (C) 2021 The Qt Company Ltd. +** Copyright (C) 2022 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -207,6 +207,14 @@ static QTimeZonePrivate::Data ucalTimeZoneTransition(UCalendar *m_ucal, status = U_ZERO_ERROR; bool ok = ucal_getTimeZoneTransitionDate(ucal, type, &tranMSecs, &status); + // Catch a known violation (in ICU 67) of the specified behavior: + if (U_SUCCESS(status) && ok && type == UCAL_TZ_TRANSITION_NEXT) { + // At the end of time, that can "succeed" with tranMSecs == + // atMSecsSinceEpoch, which should be treated as a failure. + // (At the start of time, previous correctly fails.) + ok = qint64(tranMSecs) > atMSecsSinceEpoch; + } + // Set the transition time to find the offsets for if (U_SUCCESS(status) && ok) { status = U_ZERO_ERROR; -- cgit v1.2.3