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

Reply via email to