fix(XML): fuzzing stack overflow (#4629). Limit maximum XML element depth.

This commit is contained in:
Günter Obiltschnig
2024-09-26 09:03:31 +02:00
parent 3a8c6a72b1
commit 3b4a8ea6e7
6 changed files with 76 additions and 15 deletions

View File

@@ -46,9 +46,14 @@ class XML_API DOMBuilder: protected DTDHandler, protected ContentHandler, protec
/// must be supplied to the DOMBuilder.
{
public:
DOMBuilder(XMLReader& xmlReader, NamePool* pNamePool = 0);
DOMBuilder(XMLReader& xmlReader, NamePool* pNamePool = 0, std::size_t maxDepth = 0);
/// Creates a DOMBuilder using the given XMLReader.
/// If a NamePool is given, it becomes the Document's NamePool.
///
/// The maxDepth parameter can be used to limit the maximum element depth of the
/// document. This can be used to prevent excessive element depth, which
/// could lead to a stack overflow when destroying the document.
/// A maxDepth of 0 does not limit the depth.
virtual ~DOMBuilder();
/// Destroys the DOMBuilder.
@@ -98,11 +103,13 @@ private:
XMLReader& _xmlReader;
NamePool* _pNamePool;
std::size_t _maxDepth;
Document* _pDocument;
AbstractContainerNode* _pParent;
AbstractNode* _pPrevious;
bool _inCDATA;
bool _namespaces;
std::size_t _depth;
};

View File

@@ -99,12 +99,30 @@ public:
void setEntityResolver(EntityResolver* pEntityResolver);
/// Sets the entity resolver on the underlying SAXParser.
void setMaxElementDepth(std::size_t limit);
/// Limits the maximum element depth of the XML document to be loaded.
/// Setting the limit to zero disables the limit.
///
/// This can be used to prevent excessive element depth, which
/// could lead to a stack overflow when destroying the document.
///
/// The default limit is 256.
std::size_t getMaxElementDepth() const;
/// Returns the maximum element depth.
static const XMLString FEATURE_FILTER_WHITESPACE;
enum
{
DEFAULT_MAX_ELEMENT_DEPTH = 256
};
private:
SAXParser _saxParser;
NamePool* _pNamePool;
bool _filterWhitespace;
bool _filterWhitespace = false;
std::size_t _maxElementDepth = DEFAULT_MAX_ELEMENT_DEPTH;
};