From 7a895109162c32e3899f0eabf4e4c1824f87f09b Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Sun, 14 Apr 2013 15:06:34 +0200 Subject: [PATCH] Make more key/value-type functions safe against reordered xml elements. --- src/format/KeePass2XmlReader.cpp | 62 +++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/src/format/KeePass2XmlReader.cpp b/src/format/KeePass2XmlReader.cpp index 2eb98fd8..8382098c 100644 --- a/src/format/KeePass2XmlReader.cpp +++ b/src/format/KeePass2XmlReader.cpp @@ -307,19 +307,27 @@ void KeePass2XmlReader::parseIcon() Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Icon"); Uuid uuid; + QImage icon; + bool uuidSet = false; + bool iconSet = false; + while (!m_xml.error() && m_xml.readNextStartElement()) { if (m_xml.name() == "UUID") { uuid = readUuid(); + uuidSet = true; } else if (m_xml.name() == "Data") { - QImage icon; icon.loadFromData(readBinary()); - m_meta->addCustomIcon(uuid, icon); + iconSet = true; } else { skipCurrentElement(); } } + + if (uuidSet && iconSet) { + m_meta->addCustomIcon(uuid, icon); + } } void KeePass2XmlReader::parseBinaries() @@ -372,17 +380,27 @@ void KeePass2XmlReader::parseCustomDataItem() Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Item"); QString key; + QString value; + bool keySet = false; + bool valueSet = false; + while (!m_xml.error() && m_xml.readNextStartElement()) { if (m_xml.name() == "Key") { key = readString(); + keySet = true; } else if (m_xml.name() == "Value") { - m_meta->addCustomField(key, readString()); + value = readString(); + valueSet = true; } else { skipCurrentElement(); } } + + if (keySet && valueSet) { + m_meta->addCustomField(key, value); + } } void KeePass2XmlReader::parseRoot() @@ -671,13 +689,19 @@ void KeePass2XmlReader::parseEntryString(Entry* entry) Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "String"); QString key; + QString value; + bool protect; + bool keySet = false; + bool valueSet = false; + while (!m_xml.error() && m_xml.readNextStartElement()) { if (m_xml.name() == "Key") { key = readString(); + keySet = true; } else if (m_xml.name() == "Value") { QXmlStreamAttributes attr = m_xml.attributes(); - QString value = readString(); + value = readString(); bool isProtected = attr.value("Protected") == "True"; bool protectInMemory = attr.value("ProtectInMemory") == "True"; @@ -691,12 +715,17 @@ void KeePass2XmlReader::parseEntryString(Entry* entry) } } - entry->attributes()->set(key, value, isProtected || protectInMemory); + protect = isProtected || protectInMemory; + valueSet = true; } else { skipCurrentElement(); } } + + if (keySet && valueSet) { + entry->attributes()->set(key, value, protect); + } } QPair KeePass2XmlReader::parseEntryBinary(Entry* entry) @@ -706,9 +735,14 @@ QPair KeePass2XmlReader::parseEntryBinary(Entry* entry) QPair poolRef; QString key; + QByteArray value; + bool keySet = false; + bool valueSet = false; + while (!m_xml.error() && m_xml.readNextStartElement()) { if (m_xml.name() == "Key") { key = readString(); + keySet = true; } else if (m_xml.name() == "Value") { QXmlStreamAttributes attr = m_xml.attributes(); @@ -719,7 +753,7 @@ QPair KeePass2XmlReader::parseEntryBinary(Entry* entry) } else { // format compatbility - QByteArray value = readBinary(); + value = readBinary(); bool isProtected = attr.hasAttribute("Protected") && (attr.value("Protected") == "True"); @@ -727,7 +761,7 @@ QPair KeePass2XmlReader::parseEntryBinary(Entry* entry) m_randomStream->processInPlace(value); } - entry->attachments()->set(key, value); + valueSet = true; } } else { @@ -735,6 +769,10 @@ QPair KeePass2XmlReader::parseEntryBinary(Entry* entry) } } + if (keySet && valueSet) { + entry->attachments()->set(key, value); + } + return poolRef; } @@ -766,18 +804,26 @@ void KeePass2XmlReader::parseAutoTypeAssoc(Entry* entry) Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "Association"); AutoTypeAssociations::Association assoc; + bool windowSet = false; + bool sequenceSet = false; + while (!m_xml.error() && m_xml.readNextStartElement()) { if (m_xml.name() == "Window") { assoc.window = readString(); + windowSet = true; } else if (m_xml.name() == "KeystrokeSequence") { assoc.sequence = readString(); - entry->autoTypeAssociations()->add(assoc); + sequenceSet = true; } else { skipCurrentElement(); } } + + if (windowSet && sequenceSet) { + entry->autoTypeAssociations()->add(assoc); + } } QList KeePass2XmlReader::parseEntryHistory()