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 <rle...@apache.org> 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; } --------------------------------------------------------------------- To unsubscribe, e-mail: c-dev-unsubscr...@xerces.apache.org For additional commands, e-mail: c-dev-h...@xerces.apache.org