From d90760f915ba7eda71a38245b1dc308c71724581 Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Thu, 23 Dec 2021 14:38:05 +0100 Subject: [PATCH] stabilize XML parsing --- GUI/Model/Job/JobItem.cpp | 12 ++++++---- GUI/Model/Session/SessionXML.cpp | 40 +++++++++++++++++++++++++++++--- GUI/Model/Session/SessionXML.h | 1 + 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/GUI/Model/Job/JobItem.cpp b/GUI/Model/Job/JobItem.cpp index b57af9b6755..a86d913cd1c 100644 --- a/GUI/Model/Job/JobItem.cpp +++ b/GUI/Model/Job/JobItem.cpp @@ -408,13 +408,17 @@ void JobItem::readNonSessionItems(QXmlStreamReader* reader) while (reader->readNextStartElement()) { if (reader->name() == Tags::SimulationOptions) { m_simulationOptionsItem.readContentFrom(reader); - reader->skipCurrentElement(); - } else if (reader->name() == Tags::Materials) + goToEndElementOfTag(reader, Tags::SimulationOptions); + } else if (reader->name() == Tags::Materials) { m_materials.readContentFrom(reader); - else if (reader->name() == Tags::ParameterContainer) + goToEndElementOfTag(reader, Tags::Materials); + } else if (reader->name() == Tags::ParameterContainer) { m_parameterContainer.readContentFrom(reader); - else if (reader->name() == Tags::Sample) + goToEndElementOfTag(reader, Tags::ParameterContainer); + } else if (reader->name() == Tags::Sample) { m_multiLayerItem.readContentFrom(reader); + goToEndElementOfTag(reader, Tags::Sample); + } } } diff --git a/GUI/Model/Session/SessionXML.cpp b/GUI/Model/Session/SessionXML.cpp index 50fdd049b14..3b19c2dc88e 100644 --- a/GUI/Model/Session/SessionXML.cpp +++ b/GUI/Model/Session/SessionXML.cpp @@ -26,6 +26,26 @@ namespace { +void assertCurrentTag(QXmlStreamReader* reader, const QString& expectedTag) +{ + ASSERT(reader); + + if (reader->name() != expectedTag) { +#ifdef _DEBUG + // to simplify debugging: what is the current tag + QString foundTag = reader->name().toString(); + Q_UNUSED(foundTag); +#endif + throw DeserializationException::streamError(); + } +} + +void assertCurrentToken(QXmlStreamReader* reader, QXmlStreamReader::TokenType token) +{ + if (reader->tokenType() != token) + throw DeserializationException::streamError(); +} + namespace Tags { const QString Id("id"); } // namespace Tags @@ -58,6 +78,20 @@ SessionItem* createItem(SessionItem* parent, const QString& modelType, const QSt } // namespace +void GUI::Session::XML::goToEndElementOfTag(QXmlStreamReader* reader, const QString& tag) +{ + if (reader->name() != tag) { + if (!reader->isEndElement()) + reader->skipCurrentElement(); + reader->skipCurrentElement(); + } + assertCurrentTag(reader, tag); + if (!reader->isEndElement()) + reader->skipCurrentElement(); + + assertCurrentToken(reader, QXmlStreamReader::EndElement); + assertCurrentTag(reader, tag); +} void GUI::Session::XML::writeModel(QXmlStreamWriter* writer, SessionItem* modelRootItem) { @@ -252,7 +286,7 @@ void GUI::Session::XML::readItems(QXmlStreamReader* reader, SessionItem* parent, ASSERT(reader->name() == GUI::Session::XML::ItemTag); } else if (reader->name() == GUI::Session::XML::ParameterTag) { GUI::Session::XML::readProperty(reader, parent, messageService); - ASSERT(reader->name() == GUI::Session::XML::ParameterTag); + goToEndElementOfTag(reader, GUI::Session::XML::ParameterTag); } else if (reader->name() == GUI::Session::XML::BinaryData) { if (reader->attributes().value(GUI::Session::XML::Version).toInt() == 1) { QString valueAsBase64 = @@ -262,10 +296,10 @@ void GUI::Session::XML::readItems(QXmlStreamReader* reader, SessionItem* parent, parent->deserializeBinaryData(data); } else throw DeserializationException::tooNew(); - ASSERT(reader->name() == GUI::Session::XML::BinaryData); + goToEndElementOfTag(reader, GUI::Session::XML::BinaryData); } else if (reader->name() == GUI::Session::XML::NonSessionItemData) { parent->readNonSessionItems(reader); - ASSERT(reader->name() == GUI::Session::XML::NonSessionItemData); + goToEndElementOfTag(reader, GUI::Session::XML::NonSessionItemData); } } else if (reader->isEndElement()) { if (reader->name() == GUI::Session::XML::ItemTag && parent) diff --git a/GUI/Model/Session/SessionXML.h b/GUI/Model/Session/SessionXML.h index 10e7da0a550..f7fefe608a8 100644 --- a/GUI/Model/Session/SessionXML.h +++ b/GUI/Model/Session/SessionXML.h @@ -76,6 +76,7 @@ void writeAttribute(QXmlStreamWriter* writer, const QString& attributeName, doub void writeAttribute(QXmlStreamWriter* writer, const QString& attributeBaseName, const R3& vec); void writeAttribute(QXmlStreamWriter* writer, const QString& attributeBaseName, const complex_t& c); +void goToEndElementOfTag(QXmlStreamReader* reader, const QString& tag); void readItems(QXmlStreamReader* reader, SessionItem* parent, QString topTag = "", MessageService* messageService = nullptr); QString readProperty(QXmlStreamReader* reader, SessionItem* item, -- GitLab