Add MINS_PER_HOUR constant and avoid a Coverity overflow warning

Being able to distinguish which 60 is minutes-per-hour and which is
seconds-per-minute has some value in its own right, and doing it with
qint64 values (as usual for DateTimeConstants) takes care of two
Coverity warnings about multiplying before widening.

Use the new constant, and SECS_PER_MIN, in a few other places where
the result isn't an int (we don't want to provoke narrowing warnings).

Change-Id: Iadcb6956ac22a53029bf7b7518369520d2b1fd8b
Coverity-Id: CID 393112
Coverity-Id: CID 393113
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Edward Welbourne 2022-05-23 12:31:43 +02:00
parent fd4f218c1e
commit 410b5bc238
3 changed files with 19 additions and 13 deletions

View File

@ -1984,7 +1984,7 @@ bool QTime::setHMS(int h, int m, int s, int ms)
mds = NullTime; // make this invalid
return false;
}
mds = (h * SECS_PER_HOUR + m * SECS_PER_MIN + s) * MSECS_PER_SEC + ms;
mds = ((h * MINS_PER_HOUR + m) * SECS_PER_MIN + s) * MSECS_PER_SEC + ms;
Q_ASSERT(mds >= 0 && mds < MSECS_PER_DAY);
return true;
}
@ -2194,13 +2194,13 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
if (string.size() > 2) {
if (string[2] == u':' && string.size() > 4)
minute = readInt(string.sliced(3, 2));
if (!minute.ok || minute.value >= 60)
if (!minute.ok || minute.value >= MINS_PER_HOUR)
return QTime();
} else if (format == Qt::TextDate) { // Requires minutes
return QTime();
} else if (frac.ok) {
Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
fraction *= 60;
fraction *= MINS_PER_HOUR;
minute.value = qulonglong(fraction);
fraction -= minute.value;
}
@ -2209,13 +2209,13 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
if (string.size() > 5) {
if (string[5] == u':' && string.size() == 8)
second = readInt(string.sliced(6, 2));
if (!second.ok || second.value >= 60)
if (!second.ok || second.value >= SECS_PER_MIN)
return QTime();
} else if (frac.ok) {
if (format == Qt::TextDate) // Doesn't allow fraction of minutes
return QTime();
Q_ASSERT(!(fraction < 0.0) && fraction < 1.0);
fraction *= 60;
fraction *= SECS_PER_MIN;
second.value = qulonglong(fraction);
fraction -= second.value;
}
@ -2229,9 +2229,9 @@ static QTime fromIsoTimeString(QStringView string, Qt::DateFormat format, bool *
// into other fields, do so:
if (isMidnight24 || hour.value < 23 || minute.value < 59 || second.value < 59) {
msec = 0;
if (++second.value == 60) {
if (++second.value == SECS_PER_MIN) {
second.value = 0;
if (++minute.value == 60) {
if (++minute.value == MINS_PER_HOUR) {
minute.value = 0;
++hour.value;
// May need to propagate further via isMidnight24, see below
@ -2388,7 +2388,8 @@ QTime QTime::fromString(const QString &string, QStringView format)
bool QTime::isValid(int h, int m, int s, int ms)
{
return uint(h) < 24 && uint(m) < 60 && uint(s) < SECS_PER_MIN && uint(ms) < MSECS_PER_SEC;
return (uint(h) < 24 && uint(m) < MINS_PER_HOUR && uint(s) < SECS_PER_MIN
&& uint(ms) < MSECS_PER_SEC);
}
/*****************************************************************************

View File

@ -113,9 +113,10 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QDateTimePrivate::StatusFlags)
namespace QtPrivate {
namespace DateTimeConstants {
constexpr qint64 MINS_PER_HOUR = 60;
constexpr qint64 SECS_PER_MIN = 60;
constexpr qint64 SECS_PER_HOUR = SECS_PER_MIN * 60;
constexpr qint64 SECS_PER_HOUR = SECS_PER_MIN * MINS_PER_HOUR;
constexpr qint64 SECS_PER_DAY = SECS_PER_HOUR * 24;
constexpr qint64 MSECS_PER_SEC = 1000;

View File

@ -32,6 +32,11 @@ namespace {
constexpr int tmYearFromQYear(int year) { return year - (year < 0 ? 1899 : 1900); }
constexpr int qYearFromTmYear(int year) { return year + (year < -1899 ? 1899 : 1900); }
constexpr inline qint64 tmSecsWithinDay(const struct tm &when)
{
return (when.tm_hour * MINS_PER_HOUR + when.tm_min) * SECS_PER_MIN + when.tm_sec;
}
/* If mktime() returns -1, is it really an error ?
It might return -1 because we're looking at the last second of 1969 and
@ -240,7 +245,7 @@ int getCurrentStandardUtcOffset()
#ifdef Q_OS_WIN
TIME_ZONE_INFORMATION tzInfo;
GetTimeZoneInformation(&tzInfo);
return -tzInfo.Bias * 60;
return -tzInfo.Bias * SECS_PER_MIN;
#else
qTzSet();
const time_t curr = time(nullptr);
@ -298,8 +303,7 @@ QDateTimePrivate::ZoneState utcToLocal(qint64 utcMillis)
local.tm_mon + 1, local.tm_mday, &jd))) {
return {utcMillis};
}
const qint64 daySeconds
= (local.tm_hour * 60 + local.tm_min) * 60 + local.tm_sec;
const qint64 daySeconds = tmSecsWithinDay(local);
Q_ASSERT(0 <= daySeconds && daySeconds < SECS_PER_DAY);
qint64 localSeconds, localMillis;
if (Q_UNLIKELY(
@ -351,7 +355,7 @@ QDateTimePrivate::ZoneState mapLocalTime(qint64 local, QDateTimePrivate::Dayligh
&jd))) {
return {local, offset, dst, false};
}
qint64 daySecs = tmLocal.tm_sec + 60 * (tmLocal.tm_min + 60 * tmLocal.tm_hour);
qint64 daySecs = tmSecsWithinDay(tmLocal);
Q_ASSERT(0 <= daySecs && daySecs < SECS_PER_DAY);
if (daySecs > 0 && jd < JULIAN_DAY_FOR_EPOCH) {
++jd;