Merge pull request #39 from rouault/memleak_fixes_ContentSpecNode_ComplexTypeInfo
[XERCESC-2227] Memleak fixes in ContentSpecNode and ComplexTypeInfo classes
diff --git a/src/xercesc/validators/common/ContentSpecNode.cpp b/src/xercesc/validators/common/ContentSpecNode.cpp
index 9fc0233..387dfca 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>
namespace XERCES_CPP_NAMESPACE {
@@ -52,31 +53,49 @@
, 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);
+ tmp = toCopy.getSecond();
+ if (tmp)
+ fSecond = new (fMemoryManager) ContentSpecNode(*tmp);
+ }
+ catch (const OutOfMemoryException&)
+ {
+ cleanup();
+
+ throw;
+ }
+
}
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 1b174e3..38deeb3 100644
--- a/src/xercesc/validators/common/ContentSpecNode.hpp
+++ b/src/xercesc/validators/common/ContentSpecNode.hpp
@@ -150,6 +150,8 @@
// -----------------------------------------------------------------------
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 1822e3f..ee650ce 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>
namespace XERCES_CPP_NAMESPACE {
@@ -323,10 +324,19 @@
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 @@
|| ((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 @@
}
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 @@
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 == 1 && maxOccurs == 1) {
+ }
+ else if (minOccurs == 0 && maxOccurs == 1) {
- if(minOccurs==0)
+ 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,61 @@
, true
, fMemoryManager
);
- else
+ }
+ 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))
+ {
+ retNode = new (fMemoryManager) ContentSpecNode
+ (
+ ContentSpecNode::Loop
+ , retNode
+ , 0
+ , true
+ , true
+ , fMemoryManager
+ );
+ 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
+ );
+
+ }
+ else if (maxOccurs == -1) {
+
retNode = new (fMemoryManager) ContentSpecNode
(
ContentSpecNode::OneOrMore
@@ -638,112 +691,35 @@
, fMemoryManager
);
- }
- else if (maxOccurs == -1) {
-
- retNode = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::OneOrMore
- , retNode
- , 0
- , true
- , true
- , fMemoryManager
- );
-
- for (int i=0; i < (minOccurs-1); i++) {
- retNode = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::Sequence
- , saveNode
- , retNode
- , false
- , true
- , fMemoryManager
- );
- }
- }
- else {
-
- if (minOccurs == 0) {
-
- ContentSpecNode* optional = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::ZeroOrOne
- , saveNode
- , 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) {
-
- retNode = new (fMemoryManager) ContentSpecNode
- (
- ContentSpecNode::Sequence
- , retNode
- , 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) {
+ if (minOccurs == 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++) {
+ retNode = optional;
+ for (int i=0; i < (maxOccurs-1); i++) {
retNode = new (fMemoryManager) ContentSpecNode
(
ContentSpecNode::Sequence
@@ -755,8 +731,86 @@
);
}
}
+ else {
+
+ if (minOccurs > 1) {
+
+ retNode = new (fMemoryManager) ContentSpecNode
+ (
+ ContentSpecNode::Sequence
+ , retNode
+ , 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;
}