diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2020-04-15 13:58:33 -0300 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2020-04-30 11:00:29 +0000 |
commit | 52a2505672cbb1ca8b5b32f7bc1259485c65483b (patch) | |
tree | 9acd649a7bbdc4a76f80466c1357a3f830fef2b6 /src/corelib/serialization | |
parent | 1eeabc6652220ff263eaa63872cd52c1693cbf69 (diff) |
QCborValue: avoid signed integer oveflows when decoding time_t
QDateTime::fromSecsSinceEpoch() multiplies by 1000 but does not check
for overflow. That means we must do so in QCborValue validation. We
can't use mul_overflow<qint64> on 32-bit platforms, so we do a compare-
and-branch there. For 64-bit platforms, we prefer to do the
multiplication with checked overflow, as the common case is that it will
not overflow and we'll need the multiplication anyway.
Change-Id: Ibdc95e9af7bd456a94ecfffd16060cba6f1c86b8
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/corelib/serialization')
-rw-r--r-- | src/corelib/serialization/qcborvalue.cpp | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/src/corelib/serialization/qcborvalue.cpp b/src/corelib/serialization/qcborvalue.cpp index a3729b4ef9..f5cccf1be1 100644 --- a/src/corelib/serialization/qcborvalue.cpp +++ b/src/corelib/serialization/qcborvalue.cpp @@ -788,10 +788,25 @@ static QCborValue::Type convertToExtendedType(QCborContainerPrivate *d) // The data is supposed to be US-ASCII. If it isn't (contains UTF-8), // QDateTime::fromString will fail anyway. dt = QDateTime::fromString(b->asLatin1(), Qt::ISODateWithMs); - } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Integer) { - dt = QDateTime::fromSecsSinceEpoch(e.value, Qt::UTC); - } else if (tag == qint64(QCborKnownTags::UnixTime_t) && e.type == QCborValue::Double) { - dt = QDateTime::fromMSecsSinceEpoch(qint64(e.fpvalue() * 1000), Qt::UTC); + } else if (tag == qint64(QCborKnownTags::UnixTime_t)) { + qint64 msecs; + bool ok = false; + if (e.type == QCborValue::Integer) { +#if QT_POINTER_SIZE == 8 + // we don't have a fast 64-bit mul_overflow implementation on + // 32-bit architectures. + ok = !mul_overflow(e.value, qint64(1000), &msecs); +#else + static const qint64 Limit = std::numeric_limits<qint64>::max() / 1000; + ok = (e.value > -Limit && e.value < Limit); + if (ok) + msecs = e.value * 1000; +#endif + } else if (e.type == QCborValue::Double) { + ok = convertDoubleTo(round(e.fpvalue() * 1000), &msecs); + } + if (ok) + dt = QDateTime::fromMSecsSinceEpoch(msecs, Qt::UTC); } if (dt.isValid()) { QByteArray text = dt.toString(Qt::ISODateWithMs).toLatin1(); |