From aabe80ae2895a4d7f115486c1e5f0033f33b6959 Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 22 Jun 2014 13:57:26 +0200 Subject: Make QDom/QXmlSimpleReader reentrant. I moved the evil static bool to QXmlSimpleReaderPrivate, and used it from QDom, when the reader instance is a QXmlSimpleReader (if it's not, nothing happens, like before). Task-number: QTBUG-40015 Change-Id: I54ba89db334d7b086379c4a6840cf0de23f77027 Reviewed-by: Thiago Macieira --- src/xml/dom/qdom.cpp | 23 ++++++++++++----------- src/xml/sax/qxml.cpp | 18 +++++++----------- src/xml/sax/qxml.h | 1 + src/xml/sax/qxml_p.h | 2 ++ 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index 2383bda1c9..5907a72bd6 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -54,6 +54,7 @@ #include #include #include +#include "private/qxml_p.h" #include #include #include @@ -502,7 +503,7 @@ public: ~QDomDocumentPrivate(); bool setContent(QXmlInputSource *source, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn); - bool setContent(QXmlInputSource *source, QXmlReader *reader, QString *errorMsg, int *errorLine, int *errorColumn); + bool setContent(QXmlInputSource *source, QXmlReader *reader, QXmlSimpleReader *simpleReader, QString *errorMsg, int *errorLine, int *errorColumn); // Attributes QDomDocumentTypePrivate* doctype() { return type.data(); } @@ -573,7 +574,7 @@ public: class QDomHandler : public QXmlDefaultHandler { public: - QDomHandler(QDomDocumentPrivate* d, bool namespaceProcessing); + QDomHandler(QDomDocumentPrivate* d, QXmlSimpleReader *reader, bool namespaceProcessing); ~QDomHandler(); // content handler @@ -615,6 +616,7 @@ private: bool cdata; bool nsProcessing; QXmlLocator *locator; + QXmlSimpleReader *reader; }; /************************************************************** @@ -6208,10 +6210,10 @@ bool QDomDocumentPrivate::setContent(QXmlInputSource *source, bool namespaceProc { QXmlSimpleReader reader; initializeReader(reader, namespaceProcessing); - return setContent(source, &reader, errorMsg, errorLine, errorColumn); + return setContent(source, &reader, &reader, errorMsg, errorLine, errorColumn); } -bool QDomDocumentPrivate::setContent(QXmlInputSource *source, QXmlReader *reader, QString *errorMsg, int *errorLine, int *errorColumn) +bool QDomDocumentPrivate::setContent(QXmlInputSource *source, QXmlReader *reader, QXmlSimpleReader *simpleReader, QString *errorMsg, int *errorLine, int *errorColumn) { clear(); impl = new QDomImplementationPrivate; @@ -6221,7 +6223,7 @@ bool QDomDocumentPrivate::setContent(QXmlInputSource *source, QXmlReader *reader bool namespaceProcessing = reader->feature(QLatin1String("http://xml.org/sax/features/namespaces")) && !reader->feature(QLatin1String("http://xml.org/sax/features/namespace-prefixes")); - QDomHandler hnd(this, namespaceProcessing); + QDomHandler hnd(this, simpleReader, namespaceProcessing); reader->setContentHandler(&hnd); reader->setErrorHandler(&hnd); reader->setLexicalHandler(&hnd); @@ -6758,7 +6760,7 @@ bool QDomDocument::setContent(QXmlInputSource *source, bool namespaceProcessing, impl = new QDomDocumentPrivate(); QXmlSimpleReader reader; initializeReader(reader, namespaceProcessing); - return IMPL->setContent(source, &reader, errorMsg, errorLine, errorColumn); + return IMPL->setContent(source, &reader, &reader, errorMsg, errorLine, errorColumn); } /*! @@ -6820,7 +6822,7 @@ bool QDomDocument::setContent(QXmlInputSource *source, QXmlReader *reader, QStri { if (!impl) impl = new QDomDocumentPrivate(); - return IMPL->setContent(source, reader, errorMsg, errorLine, errorColumn); + return IMPL->setContent(source, reader, 0, errorMsg, errorLine, errorColumn); } /*! @@ -7360,9 +7362,9 @@ QDomComment QDomNode::toComment() const * **************************************************************/ -QDomHandler::QDomHandler(QDomDocumentPrivate* adoc, bool namespaceProcessing) +QDomHandler::QDomHandler(QDomDocumentPrivate* adoc, QXmlSimpleReader* areader, bool namespaceProcessing) : errorLine(0), errorColumn(0), doc(adoc), node(adoc), cdata(false), - nsProcessing(namespaceProcessing), locator(0) + nsProcessing(namespaceProcessing), locator(0), reader(areader) { } @@ -7466,11 +7468,10 @@ bool QDomHandler::processingInstruction(const QString& target, const QString& da return false; } -extern bool qt_xml_skipped_entity_in_content; bool QDomHandler::skippedEntity(const QString& name) { // we can only handle inserting entity references into content - if (!qt_xml_skipped_entity_in_content) + if (reader && !reader->d_ptr->skipped_entity_in_content) return true; QDomNodePrivate *n = doc->createEntityReference(name); diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp index 7db8d5f503..50900c17f0 100644 --- a/src/xml/sax/qxml.cpp +++ b/src/xml/sax/qxml.cpp @@ -100,10 +100,6 @@ static const signed char cltDq = 12; // " static const signed char cltSq = 13; // ' static const signed char cltUnknown = 14; -// Hack for letting QDom know where the skipped entity occurred -// ### the use of this variable means the code isn't reentrant. -bool qt_xml_skipped_entity_in_content; - // character lookup table static const signed char charLookupTable[256]={ cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07 @@ -3230,7 +3226,7 @@ bool QXmlSimpleReader::parse(const QXmlInputSource *input, bool incremental) return false; } } - qt_xml_skipped_entity_in_content = false; + d->skipped_entity_in_content = false; return d->parseBeginOrContinue(0, incremental); } @@ -7594,13 +7590,13 @@ bool QXmlSimpleReaderPrivate::processReference() } if (contentHnd) { - qt_xml_skipped_entity_in_content = parseReference_context == InContent; + skipped_entity_in_content = parseReference_context == InContent; if (!contentHnd->skippedEntity(reference)) { - qt_xml_skipped_entity_in_content = false; + skipped_entity_in_content = false; reportParseError(contentHnd->errorString()); return false; // error } - qt_xml_skipped_entity_in_content = false; + skipped_entity_in_content = false; } } } else if ((*itExtern).notation.isNull()) { @@ -7630,13 +7626,13 @@ bool QXmlSimpleReaderPrivate::processReference() } } if (skipIt && contentHnd) { - qt_xml_skipped_entity_in_content = true; + skipped_entity_in_content = true; if (!contentHnd->skippedEntity(reference)) { - qt_xml_skipped_entity_in_content = false; + skipped_entity_in_content = false; reportParseError(contentHnd->errorString()); return false; // error } - qt_xml_skipped_entity_in_content = false; + skipped_entity_in_content = false; } parseReference_charDataRead = false; } break; diff --git a/src/xml/sax/qxml.h b/src/xml/sax/qxml.h index 743f8702af..2f276f75c6 100644 --- a/src/xml/sax/qxml.h +++ b/src/xml/sax/qxml.h @@ -269,6 +269,7 @@ private: QScopedPointer d_ptr; friend class QXmlSimpleReaderLocator; + friend class QDomHandler; }; // diff --git a/src/xml/sax/qxml_p.h b/src/xml/sax/qxml_p.h index 5babd98d13..1cb919a554 100644 --- a/src/xml/sax/qxml_p.h +++ b/src/xml/sax/qxml_p.h @@ -148,6 +148,8 @@ private: // used in QXmlSimpleReader::parseContent() to decide whether character // data was read bool contentCharDataRead; + // Hack for letting QDom know where the skipped entity occurred + bool skipped_entity_in_content; // helper classes QScopedPointer locator; -- cgit v1.2.3