Revision control

Copy as Markdown

// Copyright (C) 2020 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:critical reason:data-parser
// ### TODO: inline this file into qxml.cpp
#ifndef QXML_P_H
#define QXML_P_H
#include <qstack.h>
#include <qmap.h>
#include <qhash.h>
#include <qxml.h>
#include <private/qglobal_p.h>
#include <stack>
QT_BEGIN_NAMESPACE
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience of
// qxml.cpp. This header file may change from version to version without
// notice, or even be removed.
//
// We mean it.
//
class QXmlSimpleReaderPrivate
{
public:
~QXmlSimpleReaderPrivate();
private:
// functions
QXmlSimpleReaderPrivate(QXmlSimpleReader *reader);
void initIncrementalParsing();
// used to determine if elements are correctly nested
std::stack<QString, QStringList> tags;
// used by parseReference() and parsePEReference()
enum EntityRecognitionContext { InContent, InAttributeValue, InEntityValue, InDTD };
// used for entity declarations
struct ExternParameterEntity
{
ExternParameterEntity() {}
ExternParameterEntity(const QString &p, const QString &s)
: publicId(p), systemId(s) {}
QString publicId;
QString systemId;
};
friend class QTypeInfo<ExternParameterEntity>;
struct ExternEntity
{
ExternEntity() {}
ExternEntity(const QString &p, const QString &s, const QString &n)
: publicId(p), systemId(s), notation(n) {}
QString publicId;
QString systemId;
QString notation;
};
friend class QTypeInfo<ExternEntity>;
QMap<QString,ExternParameterEntity> externParameterEntities;
QMap<QString,QString> parameterEntities;
QMap<QString,ExternEntity> externEntities;
QMap<QString,QString> entities;
enum class ExpansionCheck
{
None,
GeneralEntity,
ParameterEntity,
};
// used for parsing of entity references
struct XmlRef {
XmlRef()
: index(0) {}
XmlRef(const QString &_name, const QString &_value, ExpansionCheck _check)
: name(_name), value(_value), index(0), check(_check) {}
bool isEmpty() const { return index == value.size(); }
QChar next() { return value.at(index++); }
QString name;
QString value;
qsizetype index;
ExpansionCheck check = ExpansionCheck::None;
};
friend class QTypeInfo<XmlRef>;
QStack<XmlRef> xmlRefStack;
// used for standalone declaration
enum Standalone { Yes, No, Unknown };
QString doctype; // only used for the doctype
QString xmlVersion; // only used to store the version information
QString encoding; // only used to store the encoding
Standalone standalone; // used to store the value of the standalone declaration
QString publicId; // used by parseExternalID() to store the public ID
QString systemId; // used by parseExternalID() to store the system ID
// Since publicId/systemId is used as temporary variables by parseExternalID(), it
// might overwrite the PUBLIC/SYSTEM for the document we're parsing. In effect, we would
// possibly send off an QXmlParseException that has the PUBLIC/SYSTEM of a entity declaration
// instead of those of the current document.
// Hence we have these two variables for storing the document's data.
QString thisPublicId;
QString thisSystemId;
QString attDeclEName; // use by parseAttlistDecl()
QString attDeclAName; // use by parseAttlistDecl()
// flags for some features support
bool useNamespaces;
bool useNamespacePrefixes;
bool reportWhitespaceCharData;
bool reportEntities;
// used to build the attribute list
QXmlAttributes attList;
// 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
std::unique_ptr<QXmlLocator> locator;
QXmlNamespaceSupport namespaceSupport;
// error string
QString error;
// arguments for parse functions (this is needed to allow incremental
// parsing)
bool parsePI_xmldecl;
bool parseName_useRef;
bool parseReference_charDataRead;
EntityRecognitionContext parseReference_context;
bool parseExternalID_allowPublicID;
EntityRecognitionContext parsePEReference_context;
QString parseString_s;
// for incremental parsing
struct ParseState {
typedef bool (QXmlSimpleReaderPrivate::*ParseFunction)();
ParseFunction function;
int state;
};
friend class QTypeInfo<ParseState>;
QStack<ParseState> *parseStack;
bool resumeSuspendedCall();
int tryUnwindParseStack(ParseState::ParseFunction func);
// used in parseProlog()
bool xmldecl_possible;
bool doctype_read;
// used in parseDoctype()
bool startDTDwasReported;
// used in parseString()
signed char Done;
// variables
QXmlContentHandler *contentHnd;
QXmlErrorHandler *errorHnd;
QXmlDTDHandler *dtdHnd;
QXmlEntityResolver *entityRes;
QXmlLexicalHandler *lexicalHnd;
QXmlDeclHandler *declHnd;
QXmlInputSource *inputSource;
QChar c; // the character at reading position
// The public API is int-based, range-checked in reportedPosition().
qsizetype lineNr; // number of line
qsizetype columnNr; // position in line
QChar nameArray[256]; // only used for names
QString nameValue; // only used for names
int nameArrayPos;
QChar refArray[256]; // only used for references
QString refValue; // only used for references
int refArrayPos;
QChar stringArray[256]; // used for any other strings that are parsed
QString stringValue; // used for any other strings that are parsed
int stringArrayPos;
QString emptyStr;
// The outermost entity that is currently being expanded (an internal
// general entity, or an internal parameter entity included in the DTD),
// and the amount of characters it has expanded to so far.
// The parameter entity names are stored with the '%' prefix.
QString expandedEntityName;
qsizetype expandedEntitySize = 0;
// The amount of characters that parameter entity references have contributed
// to the parameter entity value that is currently being parsed.
qsizetype includedParameterEntitySize = 0;
int entityCharacterLimit = DefaultEntityCharacterLimit;
// The limit to the amount of times the DTD parsing functions can be called
// for the DTD currently being parsed.
static const int dtdRecursionLimit = 2;
// The default maximum amount of characters an entity value may contain,
// after expansion.
static constexpr int DefaultEntityCharacterLimit = 4096;
const QString &string();
void stringClear();
void stringAddC(QChar);
inline void stringAddC() { stringAddC(c); }
const QString &name();
void nameClear();
void nameAddC(QChar);
inline void nameAddC() { nameAddC(c); }
const QString &ref();
void refClear();
void refAddC(QChar);
inline void refAddC() { refAddC(c); }
// private functions
bool eat_ws();
bool next_eat_ws();
void QT_FASTCALL next();
bool atEnd();
void init(const QXmlInputSource* i);
void initData();
bool entityExist(const QString&) const;
bool parseBeginOrContinue(int state, bool incremental);
enum class FrameType
{
Element,
Content,
ChoiceSeq,
};
enum class FrameParseResult
{
Done,
Failed,
EnterElement,
EnterContent,
EnterChoiceSeq,
};
struct FrameState
{
FrameType frame;
int state;
};
bool parseNestedFrames(FrameType outermost);
FrameParseResult parseElementFrame(int &state);
FrameParseResult parseContentFrame(int &state);
FrameParseResult parseChoiceSeqFrame(int &state);
bool parseProlog();
bool parseElement();
bool processElementEmptyTag();
bool processElementETagBegin2();
bool processElementAttribute();
bool parseMisc();
bool parseContent();
bool parsePI();
bool parseDoctype();
bool parseComment();
bool parseName();
bool parseNmtoken();
bool parseAttribute();
bool parseReference();
bool processReference();
bool parseExternalID();
bool parsePEReference();
bool parseMarkupdecl();
bool parseAttlistDecl();
bool parseAttType();
bool parseAttValue();
bool parseElementDecl();
bool parseNotationDecl();
bool parseChoiceSeq();
bool parseEntityDecl();
bool parseEntityValue();
bool parseString();
bool insertXmlRef(const QString&, const QString&, bool,
ExpansionCheck check = ExpansionCheck::None);
bool reportEndEntities();
void reportParseError(const QString& error);
typedef bool (QXmlSimpleReaderPrivate::*ParseFunction) ();
void unexpectedEof(ParseFunction where, int state);
void parseFailed(ParseFunction where, int state);
void pushParseState(ParseFunction function, int state);
bool addToExpandedEntitySize(const QString &name, const QString &value,
ExpansionCheck entityType, QString *errorMessage);
Q_DECLARE_PUBLIC(QXmlSimpleReader)
QXmlSimpleReader *q_ptr;
friend class QXmlSimpleReaderLocator;
friend class QDomHandler;
};
Q_DECLARE_TYPEINFO(QXmlSimpleReaderPrivate::ParseState, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(QXmlSimpleReaderPrivate::XmlRef, Q_RELOCATABLE_TYPE);
Q_DECLARE_TYPEINFO(QXmlSimpleReaderPrivate::ExternParameterEntity, Q_RELOCATABLE_TYPE);
Q_DECLARE_TYPEINFO(QXmlSimpleReaderPrivate::ExternEntity, Q_RELOCATABLE_TYPE);
QT_END_NAMESPACE
#endif // QXML_P_H