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 <thiago.macieira@intel.com>
bb10
David Faure 2014-06-22 13:57:26 +02:00
parent e26fa6d206
commit aabe80ae28
4 changed files with 22 additions and 22 deletions

View File

@ -54,6 +54,7 @@
#include <qtextcodec.h>
#include <qtextstream.h>
#include <qxml.h>
#include "private/qxml_p.h"
#include <qvariant.h>
#include <qmap.h>
#include <qshareddata.h>
@ -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);

View File

@ -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;

View File

@ -269,6 +269,7 @@ private:
QScopedPointer<QXmlSimpleReaderPrivate> d_ptr;
friend class QXmlSimpleReaderLocator;
friend class QDomHandler;
};
//

View File

@ -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<QXmlLocator> locator;