[xerces-c] 01/02: Merge pull request #39 from rouault/memleak_fixes_ContentSpecNode_ComplexTypeInfo
[email protected] Thu, 06 Oct 2022 12:45:52 +0000
Newsgroups
gmane.text.xml.xerces-c.devel
Message-ID
<[email protected] >
This is an automated email from the ASF dual-hosted git repository.
scantor pushed a commit to branch xerces-3.2
in repository https://gitbox.apache.org/repos/asf/xerces-c.git
commit 4e713106e3eb71c3b12b69d9d04d004c68c8447f
Author: Roger Leigh <[email protected] >
AuthorDate: Sun Oct 24 08:01:27 2021 +0100
Merge pull request #39 from rouault/memleak_fixes_ContentSpecNode_ComplexTypeInfo
[XERCESC-2227] Memleak fixes in ContentSpecNode and ComplexTypeInfo classes
---
src/xercesc/validators/common/ContentSpecNode.cpp | 41 ++-
src/xercesc/validators/common/ContentSpecNode.hpp | 2 +
src/xercesc/validators/schema/ComplexTypeInfo.cpp | 308 +++++++++++++---------
3 files changed, 213 insertions(+), 138 deletions(-)
diff --git a/src/xercesc/validators/common/ContentSpecNode.cpp b/src/xercesc/validators/common/ContentSpecNode.cpp
index 7f2627bf8..0be134f8f 100644
--- a/src/xercesc/validators/common/ContentSpecNode.cpp
+++ b/src/xercesc/validators/common/ContentSpecNode.cpp
@@ -26,6 +26,7 @@
#include <xercesc/framework/XMLBuffer.hpp>
#include <xercesc/validators/common/ContentSpecNode.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
+#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/util/ValueStackOf.hpp>
XERCES_CPP_NAMESPACE_BEGIN
@@ -52,31 +53,49 @@ ContentSpecNode::ContentSpecNode(const ContentSpecNode& toCopy) :
, fMinOccurs(toCopy.fMinOccurs)
, fMaxOccurs(toCopy.fMaxOccurs)
{
- const QName* tempElement = toCopy.getElement();
- if (tempElement)
- fElement = new (fMemoryManager) QName(*tempElement);
+ try
+ {
+ const QName* tempElement = toCopy.getElement();
+ if (tempElement)
+ fElement = new (fMemoryManager) QName(*tempElement);
- const ContentSpecNode *tmp = toCopy.getFirst();
- if (tmp)
- fFirst = new (fMemoryManager) ContentSpecNode(*tmp);
+ const ContentSpecNode *tmp = toCopy.getFirst();
+ if (tmp)
+ fFirst = new (fMemoryManager) ContentSpecNode(*tmp);
+
+ tmp = toCopy.getSecond();
+ if (tmp)
+ fSecond = new (fMemoryManager) ContentSpecNode(*tmp);
+ }
+ catch (const OutOfMemoryException&)
+ {
+ cleanup();
+
+ throw;
+ }
- tmp = toCopy.getSecond();
- if (tmp)
- fSecond = new (fMemoryManager) ContentSpecNode(*tmp);
}
ContentSpecNode::~ContentSpecNode()
+{
+ cleanup();
+}
+
+void ContentSpecNode::cleanup()
{
// Delete our children, avoiding recursive cleanup
if (fAdoptFirst && fFirst) {
- deleteChildNode(fFirst);
+ deleteChildNode(fFirst);
+ fFirst = NULL;
}
if (fAdoptSecond && fSecond) {
- deleteChildNode(fSecond);
+ deleteChildNode(fSecond);
+ fSecond = NULL;
}
delete fElement;
+ fElement = NULL;
}
void ContentSpecNode::deleteChildNode(ContentSpecNode* node)
diff --git a/src/xercesc/validators/common/ContentSpecNode.hpp b/src/xercesc/validators/common/ContentSpecNode.hpp
index 24604c616..32f6264b9 100644
--- a/src/xercesc/validators/common/ContentSpecNode.hpp
+++ b/src/xercesc/validators/common/ContentSpecNode.hpp
@@ -150,6 +150,8 @@ private :
// -----------------------------------------------------------------------
ContentSpecNode& operator=(const ContentSpecNode&);
+ void cleanup();
+
// -----------------------------------------------------------------------
// Helper functions
// -----------------------------------------------------------------------
diff --git a/src/xercesc/validators/schema/ComplexTypeInfo.cpp b/src/xercesc/validators/schema/ComplexTypeInfo.cpp
index 48f1860f4..7f650eb6f 100644
--- a/src/xercesc/validators/schema/ComplexTypeInfo.cpp
+++ b/src/xercesc/validators/schema/ComplexTypeInfo.cpp
@@ -32,6 +32,7 @@
#include <xercesc/validators/common/SimpleContentModel.hpp>
#include <xercesc/validators/schema/XSDLocator.hpp>
#include <xercesc/internal/XTemplateSerializer.hpp>
+#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/util/XMLInitializer.hpp>
XERCES_CPP_NAMESPACE_BEGIN
@@ -323,10 +324,19 @@ XMLContentModel* ComplexTypeInfo::makeContentModel(bool checkUPA)
ContentSpecNode* aSpecNode = new (fMemoryManager) ContentSpecNode(*fContentSpec);
if (checkUPA) {
- fContentSpecOrgURI = (unsigned int*) fMemoryManager->allocate
- (
- fContentSpecOrgURISize * sizeof(unsigned int)
- ); //new unsigned int[fContentSpecOrgURISize];
+ try
+ {
+ fContentSpecOrgURI = (unsigned int*) fMemoryManager->allocate
+ (
+ fContentSpecOrgURISize * sizeof(unsigned int)
+ ); //new unsigned int[fContentSpecOrgURISize];
+ }
+ catch (const OutOfMemoryException&)
+ {
+ delete aSpecNode;
+
+ throw;
+ }
}
aSpecNode = convertContentSpecTree(aSpecNode, checkUPA, useRepeatingLeafNodes(aSpecNode));
@@ -516,12 +526,31 @@ ComplexTypeInfo::convertContentSpecTree(ContentSpecNode* const curNode,
|| ((curType & 0x0f) == ContentSpecNode::Sequence))
{
ContentSpecNode* childNode = curNode->getFirst();
- ContentSpecNode* leftNode = convertContentSpecTree(childNode, checkUPA, bAllowCompactSyntax);
+ ContentSpecNode* leftNode;
+ try
+ {
+ leftNode = convertContentSpecTree(childNode, checkUPA, bAllowCompactSyntax);
+ }
+ catch( const OutOfMemoryException& )
+ {
+ curNode->setAdoptFirst(false);
+ delete curNode;
+ throw;
+ }
ContentSpecNode* rightNode = curNode->getSecond();
if (!rightNode) {
- retNode = expandContentModel(leftNode, minOccurs, maxOccurs, bAllowCompactSyntax);
+ try
+ {
+ retNode = expandContentModel(leftNode, minOccurs, maxOccurs, bAllowCompactSyntax);
+ }
+ catch( const OutOfMemoryException& )
+ {
+ curNode->setAdoptFirst(false);
+ delete curNode;
+ throw;
+ }
curNode->setAdoptFirst(false);
delete curNode;
return retNode;
@@ -535,7 +564,16 @@ ComplexTypeInfo::convertContentSpecTree(ContentSpecNode* const curNode,
}
childNode = rightNode;
- rightNode = convertContentSpecTree(childNode, checkUPA, bAllowCompactSyntax);
+ try
+ {
+ rightNode = convertContentSpecTree(childNode, checkUPA, bAllowCompactSyntax);
+ }
+ catch( const OutOfMemoryException& )
+ {
+ curNode->setAdoptSecond(false);
+ delete curNode;
+ throw;
+ }
if (rightNode != childNode) {
@@ -559,65 +597,26 @@ ContentSpecNode* ComplexTypeInfo::expandContentModel(ContentSpecNode* const spec
return 0;
}
- ContentSpecNode* saveNode = specNode;
+ ContentSpecNode* const saveNode = specNode;
ContentSpecNode* retNode = specNode;
- if (minOccurs == 1 && maxOccurs == 1) {
- }
- else if (minOccurs == 0 && maxOccurs == 1) {
-
- retNode = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::ZeroOrOne
- , retNode
- , 0
- , true
- , true
- , fMemoryManager
- );
- }
- else if (minOccurs == 0 && maxOccurs == -1) {
- retNode = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::ZeroOrMore
- , retNode
- , 0
- , true
- , true
- , fMemoryManager
- );
- }
- else if (minOccurs == 1 && maxOccurs == -1) {
- retNode = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::OneOrMore
- , retNode
- , 0
- , true
- , true
- , fMemoryManager
- );
- }
- // if what is being repeated is a leaf avoid expanding the tree
- else if(bAllowCompactSyntax &&
- (saveNode->getType()==ContentSpecNode::Leaf ||
- (saveNode->getType() & 0x0f)==ContentSpecNode::Any ||
- (saveNode->getType() & 0x0f)==ContentSpecNode::Any_Other ||
- (saveNode->getType() & 0x0f)==ContentSpecNode::Any_NS))
+ try
{
- retNode = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::Loop
- , retNode
- , 0
- , true
- , true
- , fMemoryManager
- );
- retNode->setMinOccurs(minOccurs);
- retNode->setMaxOccurs(maxOccurs);
-
- if(minOccurs==0)
+ if (minOccurs == 1 && maxOccurs == 1) {
+ }
+ else if (minOccurs == 0 && maxOccurs == 1) {
+
+ retNode = new (fMemoryManager) ContentSpecNode
+ (
+ ContentSpecNode::ZeroOrOne
+ , retNode
+ , 0
+ , true
+ , true
+ , fMemoryManager
+ );
+ }
+ else if (minOccurs == 0 && maxOccurs == -1) {
retNode = new (fMemoryManager) ContentSpecNode
(
ContentSpecNode::ZeroOrMore
@@ -627,7 +626,8 @@ ContentSpecNode* ComplexTypeInfo::expandContentModel(ContentSpecNode* const spec
, true
, fMemoryManager
);
- else
+ }
+ else if (minOccurs == 1 && maxOccurs == -1) {
retNode = new (fMemoryManager) ContentSpecNode
(
ContentSpecNode::OneOrMore
@@ -637,126 +637,180 @@ ContentSpecNode* ComplexTypeInfo::expandContentModel(ContentSpecNode* const spec
, true
, fMemoryManager
);
-
- }
- else if (maxOccurs == -1) {
-
- retNode = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::OneOrMore
- , retNode
- , 0
- , true
- , true
- , fMemoryManager
- );
-
- for (int i=0; i < (minOccurs-1); i++) {
+ }
+ // if what is being repeated is a leaf avoid expanding the tree
+ else if(bAllowCompactSyntax &&
+ (saveNode->getType()==ContentSpecNode::Leaf ||
+ (saveNode->getType() & 0x0f)==ContentSpecNode::Any ||
+ (saveNode->getType() & 0x0f)==ContentSpecNode::Any_Other ||
+ (saveNode->getType() & 0x0f)==ContentSpecNode::Any_NS))
+ {
retNode = new (fMemoryManager) ContentSpecNode
(
- ContentSpecNode::Sequence
- , saveNode
+ ContentSpecNode::Loop
, retNode
- , false
+ , 0
+ , true
, true
, fMemoryManager
);
- }
- }
- else {
+ retNode->setMinOccurs(minOccurs);
+ retNode->setMaxOccurs(maxOccurs);
+
+ if(minOccurs==0)
+ retNode = new (fMemoryManager) ContentSpecNode
+ (
+ ContentSpecNode::ZeroOrMore
+ , retNode
+ , 0
+ , true
+ , true
+ , fMemoryManager
+ );
+ else
+ retNode = new (fMemoryManager) ContentSpecNode
+ (
+ ContentSpecNode::OneOrMore
+ , retNode
+ , 0
+ , true
+ , true
+ , fMemoryManager
+ );
- if (minOccurs == 0) {
+ }
+ else if (maxOccurs == -1) {
- ContentSpecNode* optional = new (fMemoryManager) ContentSpecNode
+ retNode = new (fMemoryManager) ContentSpecNode
(
- ContentSpecNode::ZeroOrOne
- , saveNode
+ ContentSpecNode::OneOrMore
+ , retNode
, 0
, true
, true
, fMemoryManager
);
- retNode = optional;
-
- for (int i=0; i < (maxOccurs-1); i++) {
+ for (int i=0; i < (minOccurs-1); i++) {
retNode = new (fMemoryManager) ContentSpecNode
(
ContentSpecNode::Sequence
+ , saveNode
, retNode
- , optional
- , true
, false
+ , true
, fMemoryManager
);
}
}
else {
- if (minOccurs > 1) {
+ if (minOccurs == 0) {
- retNode = new (fMemoryManager) ContentSpecNode
+ ContentSpecNode* optional = new (fMemoryManager) ContentSpecNode
(
- ContentSpecNode::Sequence
- , retNode
+ ContentSpecNode::ZeroOrOne
, saveNode
+ , 0
+ , true
, true
- , false
, fMemoryManager
);
- for (int i=1; i < (minOccurs-1); i++) {
+ retNode = optional;
+
+ for (int i=0; i < (maxOccurs-1); i++) {
retNode = new (fMemoryManager) ContentSpecNode
(
ContentSpecNode::Sequence
, retNode
- , saveNode
+ , optional
, true
, false
, fMemoryManager
);
}
}
+ else {
- int counter = maxOccurs-minOccurs;
-
- if (counter > 0) {
-
- ContentSpecNode* optional = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::ZeroOrOne
- , saveNode
- , 0
- , false
- , true
- , fMemoryManager
- );
-
- retNode = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::Sequence
- , retNode
- , optional
- , true
- , true
- , fMemoryManager
- );
-
- for (int j=1; j < counter; j++) {
+ if (minOccurs > 1) {
retNode = new (fMemoryManager) ContentSpecNode
(
ContentSpecNode::Sequence
, retNode
- , optional
+ , saveNode
, true
, false
, fMemoryManager
);
+
+ for (int i=1; i < (minOccurs-1); i++) {
+ retNode = new (fMemoryManager) ContentSpecNode
+ (
+ ContentSpecNode::Sequence
+ , retNode
+ , saveNode
+ , true
+ , false
+ , fMemoryManager
+ );
+ }
+ }
+
+ int counter = maxOccurs-minOccurs;
+
+ if (counter > 0) {
+
+ ContentSpecNode* optional = new (fMemoryManager) ContentSpecNode
+ (
+ ContentSpecNode::ZeroOrOne
+ , saveNode
+ , 0
+ , false
+ , true
+ , fMemoryManager
+ );
+
+ try
+ {
+ retNode = new (fMemoryManager) ContentSpecNode
+ (
+ ContentSpecNode::Sequence
+ , retNode
+ , optional
+ , true
+ , true
+ , fMemoryManager
+ );
+ }
+ catch( const OutOfMemoryException& )
+ {
+ delete optional;
+ throw;
+ }
+
+ for (int j=1; j < counter; j++) {
+
+ retNode = new (fMemoryManager) ContentSpecNode
+ (
+ ContentSpecNode::Sequence
+ , retNode
+ , optional
+ , true
+ , false
+ , fMemoryManager
+ );
+ }
}
}
}
}
+ catch( const OutOfMemoryException& )
+ {
+ delete retNode;
+ throw;
+ }
return retNode;
}