Explorar o código

remove all usage of QDateTime::toTime_t() to avoid overflow

QDateTime::toTime_t() can overflow if called with a date outside its
domain of working

this method is obsolete and QDateTime::toSecsSinceEpoch() is the
replacement

Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
Matthieu Gallien %!s(int64=4) %!d(string=hai) anos
pai
achega
541447723a

+ 1 - 1
src/gui/userstatusselectormodel.cpp

@@ -436,7 +436,7 @@ QString UserStatusSelectorModel::clearAtReadable(const Optional<ClearAt> &clearA
         }
 
         case ClearAtType::Timestamp: {
-            const int difference = static_cast<int>(clearAt->_timestamp - _dateTimeProvider->currentDateTime().toTime_t());
+            const int difference = static_cast<int>(clearAt->_timestamp - _dateTimeProvider->currentDateTime().toSecsSinceEpoch());
             return timeDifferenceToString(difference);
         }
 

+ 4 - 1
src/libsync/discoveryphase.cpp

@@ -407,7 +407,10 @@ static void propertyMapToRemoteInfo(const QMap<QString, QString> &map, RemoteInf
         } else if (property == QLatin1String("getlastmodified")) {
             const auto date = QDateTime::fromString(value, Qt::RFC2822Date);
             Q_ASSERT(date.isValid());
-            result.modtime = date.toTime_t();
+            result.modtime = 0;
+            if (date.toSecsSinceEpoch() > 0) {
+                result.modtime = date.toSecsSinceEpoch();
+            }
         } else if (property == QLatin1String("getcontentlength")) {
             // See #4573, sometimes negative size values are returned
             bool ok = false;

+ 4 - 4
src/libsync/ocsuserstatusconnector.cpp

@@ -110,18 +110,18 @@ quint64 clearAtEndOfToTimestamp(const OCC::ClearAt &clearAt)
     Q_ASSERT(clearAt._type == OCC::ClearAtType::EndOf);
 
     if (clearAt._endof == "day") {
-        return QDate::currentDate().addDays(1).startOfDay().toTime_t();
+        return QDate::currentDate().addDays(1).startOfDay().toSecsSinceEpoch();
     } else if (clearAt._endof == "week") {
         const auto days = Qt::Sunday - QDate::currentDate().dayOfWeek();
-        return QDate::currentDate().addDays(days + 1).startOfDay().toTime_t();
+        return QDate::currentDate().addDays(days + 1).startOfDay().toSecsSinceEpoch();
     }
     qCWarning(lcOcsUserStatusConnector) << "Can not handle clear at endof day type" << clearAt._endof;
-    return QDateTime::currentDateTime().toTime_t();
+    return QDateTime::currentDateTime().toSecsSinceEpoch();
 }
 
 quint64 clearAtPeriodToTimestamp(const OCC::ClearAt &clearAt)
 {
-    return QDateTime::currentDateTime().addSecs(clearAt._period).toTime_t();
+    return QDateTime::currentDateTime().addSecs(clearAt._period).toSecsSinceEpoch();
 }
 
 quint64 clearAtToTimestamp(const OCC::ClearAt &clearAt)

+ 62 - 0
test/testlocaldiscovery.cpp

@@ -386,6 +386,68 @@ private slots:
         qDebug() << expectedState;
         QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
     }
+
+    void testInvalidMtimeRecovery()
+    {
+        FakeFolder fakeFolder{FileInfo{}};
+        QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState());
+        const QString fooFileRootFolder("foo");
+        const QString barFileRootFolder("bar");
+        const QString blaFileRootFolder("bla");
+        const QString fooFileSubFolder("subfolder/foo");
+        const QString barFileSubFolder("subfolder/bar");
+        const QString blaFileSubFolder("subfolder/bla");
+
+        fakeFolder.remoteModifier().insert(fooFileRootFolder);
+        fakeFolder.remoteModifier().insert(barFileRootFolder);
+        fakeFolder.remoteModifier().insert(blaFileRootFolder);
+        fakeFolder.remoteModifier().mkdir(QStringLiteral("subfolder"));
+        fakeFolder.remoteModifier().insert(fooFileSubFolder);
+        fakeFolder.remoteModifier().insert(barFileSubFolder);
+        fakeFolder.remoteModifier().insert(blaFileSubFolder);
+
+        QVERIFY(fakeFolder.syncOnce());
+
+        fakeFolder.remoteModifier().setModTime(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(0));
+        fakeFolder.remoteModifier().setModTime(barFileRootFolder, QDateTime::fromSecsSinceEpoch(0));
+        fakeFolder.remoteModifier().setModTime(blaFileRootFolder, QDateTime::fromSecsSinceEpoch(0));
+        fakeFolder.remoteModifier().setModTime(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(0));
+        fakeFolder.remoteModifier().setModTime(barFileSubFolder, QDateTime::fromSecsSinceEpoch(0));
+        fakeFolder.remoteModifier().setModTime(blaFileSubFolder, QDateTime::fromSecsSinceEpoch(0));
+        fakeFolder.localModifier().setModTime(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(0));
+        fakeFolder.localModifier().setModTime(barFileRootFolder, QDateTime::fromSecsSinceEpoch(0));
+        fakeFolder.localModifier().setModTime(blaFileRootFolder, QDateTime::fromSecsSinceEpoch(0));
+        fakeFolder.localModifier().setModTime(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(0));
+        fakeFolder.localModifier().setModTime(barFileSubFolder, QDateTime::fromSecsSinceEpoch(0));
+        fakeFolder.localModifier().setModTime(blaFileSubFolder, QDateTime::fromSecsSinceEpoch(0));
+
+        QVERIFY(fakeFolder.syncOnce());
+
+        QVERIFY(fakeFolder.syncOnce());
+
+        auto expectedState = fakeFolder.currentLocalState();
+        QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
+
+        fakeFolder.remoteModifier().setModTime(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(-3600));
+        fakeFolder.remoteModifier().setModTime(barFileRootFolder, QDateTime::fromSecsSinceEpoch(-3600));
+        fakeFolder.remoteModifier().setModTime(blaFileRootFolder, QDateTime::fromSecsSinceEpoch(-3600));
+        fakeFolder.remoteModifier().setModTime(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(-3600));
+        fakeFolder.remoteModifier().setModTime(barFileSubFolder, QDateTime::fromSecsSinceEpoch(-3600));
+        fakeFolder.remoteModifier().setModTime(blaFileSubFolder, QDateTime::fromSecsSinceEpoch(-3600));
+        fakeFolder.localModifier().setModTime(fooFileRootFolder, QDateTime::fromSecsSinceEpoch(-3600));
+        fakeFolder.localModifier().setModTime(barFileRootFolder, QDateTime::fromSecsSinceEpoch(-3600));
+        fakeFolder.localModifier().setModTime(blaFileRootFolder, QDateTime::fromSecsSinceEpoch(-3600));
+        fakeFolder.localModifier().setModTime(fooFileSubFolder, QDateTime::fromSecsSinceEpoch(-3600));
+        fakeFolder.localModifier().setModTime(barFileSubFolder, QDateTime::fromSecsSinceEpoch(-3600));
+        fakeFolder.localModifier().setModTime(blaFileSubFolder, QDateTime::fromSecsSinceEpoch(-3600));
+
+        QVERIFY(!fakeFolder.syncOnce());
+
+        QVERIFY(!fakeFolder.syncOnce());
+
+        expectedState = fakeFolder.currentLocalState();
+        QCOMPARE(fakeFolder.currentRemoteState(), expectedState);
+    }
 };
 
 QTEST_GUILESS_MAIN(TestLocalDiscovery)

+ 9 - 9
test/testsetuserstatusdialog.cpp

@@ -158,7 +158,7 @@ createFakePredefinedStatuses(const QDateTime &currentTime)
     OCC::Optional<OCC::ClearAt> userStatusClearAt;
     OCC::ClearAt clearAt;
     clearAt._type = OCC::ClearAtType::Timestamp;
-    clearAt._timestamp = currentTime.addSecs(60 * 60).toTime_t();
+    clearAt._timestamp = currentTime.addSecs(60 * 60).toSecsSinceEpoch();
     userStatusClearAt = clearAt;
 
     statuses.emplace_back(userStatusId, userStatusMessage, userStatusIcon,
@@ -198,7 +198,7 @@ private slots:
         {
             OCC::ClearAt clearAt;
             clearAt._type = OCC::ClearAtType::Timestamp;
-            clearAt._timestamp = currentDateTime.addDays(1).toTime_t();
+            clearAt._timestamp = currentDateTime.addDays(1).toSecsSinceEpoch();
             userStatusClearAt = clearAt;
         }
 
@@ -488,7 +488,7 @@ private slots:
             OCC::UserStatus userStatus;
             OCC::ClearAt clearAt;
             clearAt._type = OCC::ClearAtType::Timestamp;
-            clearAt._timestamp = currentTime.addSecs(30).toTime_t();
+            clearAt._timestamp = currentTime.addSecs(30).toSecsSinceEpoch();
             userStatus.setClearAt(clearAt);
 
             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
@@ -503,7 +503,7 @@ private slots:
             OCC::UserStatus userStatus;
             OCC::ClearAt clearAt;
             clearAt._type = OCC::ClearAtType::Timestamp;
-            clearAt._timestamp = currentTime.addSecs(60).toTime_t();
+            clearAt._timestamp = currentTime.addSecs(60).toSecsSinceEpoch();
             userStatus.setClearAt(clearAt);
 
             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
@@ -518,7 +518,7 @@ private slots:
             OCC::UserStatus userStatus;
             OCC::ClearAt clearAt;
             clearAt._type = OCC::ClearAtType::Timestamp;
-            clearAt._timestamp = currentTime.addSecs(60 * 30).toTime_t();
+            clearAt._timestamp = currentTime.addSecs(60 * 30).toSecsSinceEpoch();
             userStatus.setClearAt(clearAt);
 
             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
@@ -533,7 +533,7 @@ private slots:
             OCC::UserStatus userStatus;
             OCC::ClearAt clearAt;
             clearAt._type = OCC::ClearAtType::Timestamp;
-            clearAt._timestamp = currentTime.addSecs(60 * 60).toTime_t();
+            clearAt._timestamp = currentTime.addSecs(60 * 60).toSecsSinceEpoch();
             userStatus.setClearAt(clearAt);
 
             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
@@ -548,7 +548,7 @@ private slots:
             OCC::UserStatus userStatus;
             OCC::ClearAt clearAt;
             clearAt._type = OCC::ClearAtType::Timestamp;
-            clearAt._timestamp = currentTime.addSecs(60 * 60 * 4).toTime_t();
+            clearAt._timestamp = currentTime.addSecs(60 * 60 * 4).toSecsSinceEpoch();
             userStatus.setClearAt(clearAt);
 
             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
@@ -563,7 +563,7 @@ private slots:
             OCC::UserStatus userStatus;
             OCC::ClearAt clearAt;
             clearAt._type = OCC::ClearAtType::Timestamp;
-            clearAt._timestamp = currentTime.addDays(1).toTime_t();
+            clearAt._timestamp = currentTime.addDays(1).toSecsSinceEpoch();
             userStatus.setClearAt(clearAt);
 
             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();
@@ -578,7 +578,7 @@ private slots:
             OCC::UserStatus userStatus;
             OCC::ClearAt clearAt;
             clearAt._type = OCC::ClearAtType::Timestamp;
-            clearAt._timestamp = currentTime.addDays(7).toTime_t();
+            clearAt._timestamp = currentTime.addDays(7).toSecsSinceEpoch();
             userStatus.setClearAt(clearAt);
 
             auto fakeDateTimeProvider = std::make_unique<FakeDateTimeProvider>();

+ 0 - 2
test/testsyncjournaldb.cpp

@@ -107,8 +107,6 @@ private slots:
             QVERIFY(storedRecord._remotePerm == record._remotePerm);
             QVERIFY(storedRecord._checksumHeader == record._checksumHeader);
 
-            // qDebug()<< "OOOOO " << storedRecord._modtime.toTime_t() << record._modtime.toTime_t();
-
             // Attention: compare time_t types here, as QDateTime seem to maintain
             // milliseconds internally, which disappear in sqlite. Go for full seconds here.
             QVERIFY(storedRecord._modtime == record._modtime);