summaryrefslogtreecommitdiffstats
path: root/src/corelib/serialization
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2020-04-15 13:58:33 -0300
committerEdward Welbourne <edward.welbourne@qt.io>2020-04-30 11:00:29 +0000
commit52a2505672cbb1ca8b5b32f7bc1259485c65483b (patch)
tree9acd649a7bbdc4a76f80466c1357a3f830fef2b6 /src/corelib/serialization
parent1eeabc6652220ff263eaa63872cd52c1693cbf69 (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.cpp23
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();