diff --git a/src/core/Entry.cpp b/src/core/Entry.cpp index 784b489cd..1bc89e990 100644 --- a/src/core/Entry.cpp +++ b/src/core/Entry.cpp @@ -372,7 +372,6 @@ const QList& Entry::historyItems() const void Entry::addHistoryItem(Entry* entry) { Q_ASSERT(!entry->parent()); - Q_ASSERT(entry->uuid() == uuid()); m_history.append(entry); Q_EMIT modified(); diff --git a/src/format/KeePass2XmlReader.cpp b/src/format/KeePass2XmlReader.cpp index 815cbf9c2..2e76c2a90 100644 --- a/src/format/KeePass2XmlReader.cpp +++ b/src/format/KeePass2XmlReader.cpp @@ -778,6 +778,13 @@ Entry* KeePass2XmlReader::parseEntry(bool history) } Q_FOREACH (Entry* historyItem, historyItems) { + if (historyItem->uuid() != entry->uuid()) { + if (m_strictMode) { + raiseError("History element with different uuid"); + } else { + historyItem->setUuid(entry->uuid()); + } + } entry->addHistoryItem(historyItem); } diff --git a/tests/TestKeePass2XmlReader.cpp b/tests/TestKeePass2XmlReader.cpp index dd8132708..014587f48 100644 --- a/tests/TestKeePass2XmlReader.cpp +++ b/tests/TestKeePass2XmlReader.cpp @@ -407,6 +407,8 @@ void TestKeePass2XmlReader::testBroken_data() QTest::newRow("BrokenGroupReference (not strict)") << "BrokenGroupReference" << false << false; QTest::newRow("BrokenDeletedObjects (strict)") << "BrokenDeletedObjects" << true << true; QTest::newRow("BrokenDeletedObjects (not strict)") << "BrokenDeletedObjects" << false << false; + QTest::newRow("BrokenDifferentEntryHistoryUuid (strict)") << "BrokenDifferentEntryHistoryUuid" << true << true; + QTest::newRow("BrokenDifferentEntryHistoryUuid (not strict)") << "BrokenDifferentEntryHistoryUuid" << false << false; } void TestKeePass2XmlReader::testEmptyUuids() @@ -487,6 +489,32 @@ void TestKeePass2XmlReader::testInvalidXmlChars() QCOMPARE(strToBytes(attrRead->value("SurrogateValid2")), strToBytes(strSurrogateValid2)); } +void TestKeePass2XmlReader::testRepairUuidHistoryItem() +{ + KeePass2XmlReader reader; + QString xmlFile = QString("%1/%2.xml").arg(KEEPASSX_TEST_DATA_DIR, "BrokenDifferentEntryHistoryUuid"); + QVERIFY(QFile::exists(xmlFile)); + QScopedPointer db(reader.readDatabase(xmlFile)); + if (reader.hasError()) { + qWarning("Database read error: %s", qPrintable(reader.errorString())); + } + QVERIFY(!reader.hasError()); + + + + QList entries = db.data()->rootGroup()->entries(); + QCOMPARE(entries.size(), 1); + Entry* entry = entries.at(0); + + QList historyItems = entry->historyItems(); + QCOMPARE(historyItems.size(), 1); + Entry* historyItem = historyItems.at(0); + + QVERIFY(!entry->uuid().isNull()); + QVERIFY(!historyItem->uuid().isNull()); + QCOMPARE(historyItem->uuid(), entry->uuid()); +} + void TestKeePass2XmlReader::cleanupTestCase() { delete m_db; diff --git a/tests/TestKeePass2XmlReader.h b/tests/TestKeePass2XmlReader.h index b9be7b553..ff83e2597 100644 --- a/tests/TestKeePass2XmlReader.h +++ b/tests/TestKeePass2XmlReader.h @@ -43,6 +43,7 @@ private Q_SLOTS: void testBroken_data(); void testEmptyUuids(); void testInvalidXmlChars(); + void testRepairUuidHistoryItem(); void cleanupTestCase(); private: diff --git a/tests/data/BrokenDifferentEntryHistoryUuid.xml b/tests/data/BrokenDifferentEntryHistoryUuid.xml new file mode 100644 index 000000000..c07f03aa7 --- /dev/null +++ b/tests/data/BrokenDifferentEntryHistoryUuid.xml @@ -0,0 +1,17 @@ + + + + + lmU+9n0aeESKZvcEze+bRg== + Test + + MTExMTExMTExMTExMTExMQ== + + + MjIyMjIyMjIyMjIyMjIyMg== + + + + + +