You are viewing a plain text version of this content. The canonical link for it is here.
Posted to c-dev@xerces.apache.org by rl...@apache.org on 2021/10/24 07:01:52 UTC
[xerces-c] branch master updated: DFAContentModel: fix memory leaks
when OutOfMemoryException occurs
This is an automated email from the ASF dual-hosted git repository.
rleigh pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/xerces-c.git
The following commit(s) were added to refs/heads/master by this push:
new a65990d DFAContentModel: fix memory leaks when OutOfMemoryException occurs
new 6d5e52d Merge pull request #40 from rouault/fix_memleaks_DFAContentModel
a65990d is described below
commit a65990d79d3fc333d7481f010da4e165a88b6cb3
Author: Even Rouault <ev...@spatialys.com>
AuthorDate: Thu Sep 23 16:50:38 2021 +0200
DFAContentModel: fix memory leaks when OutOfMemoryException occurs
Fixes GDAL's https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=39159
---
src/xercesc/validators/common/CMStateSet.hpp | 11 +-
src/xercesc/validators/common/DFAContentModel.cpp | 178 +++++++++++++++++-----
src/xercesc/validators/common/DFAContentModel.hpp | 1 +
3 files changed, 147 insertions(+), 43 deletions(-)
diff --git a/src/xercesc/validators/common/CMStateSet.hpp b/src/xercesc/validators/common/CMStateSet.hpp
index 6e4a393..4cfc85f 100644
--- a/src/xercesc/validators/common/CMStateSet.hpp
+++ b/src/xercesc/validators/common/CMStateSet.hpp
@@ -32,6 +32,7 @@
//
#include <xercesc/util/ArrayIndexOutOfBoundsException.hpp>
+#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/util/RuntimeException.hpp>
#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/framework/MemoryManager.hpp>
@@ -93,7 +94,15 @@ public :
fDynamicBuffer->fArraySize = fBitCount / CMSTATE_BITFIELD_CHUNK;
if (fBitCount % CMSTATE_BITFIELD_CHUNK)
fDynamicBuffer->fArraySize++;
- fDynamicBuffer->fBitArray = (XMLInt32**) fDynamicBuffer->fMemoryManager->allocate(fDynamicBuffer->fArraySize*sizeof(XMLInt32*));
+ try
+ {
+ fDynamicBuffer->fBitArray = (XMLInt32**) fDynamicBuffer->fMemoryManager->allocate(fDynamicBuffer->fArraySize*sizeof(XMLInt32*));
+ }
+ catch( const OutOfMemoryException& )
+ {
+ fDynamicBuffer->fMemoryManager->deallocate(fDynamicBuffer);
+ throw;
+ }
for(XMLSize_t index = 0; index < fDynamicBuffer->fArraySize; index++)
fDynamicBuffer->fBitArray[index]=NULL;
}
diff --git a/src/xercesc/validators/common/DFAContentModel.cpp b/src/xercesc/validators/common/DFAContentModel.cpp
index 5030565..ddca8ec 100644
--- a/src/xercesc/validators/common/DFAContentModel.cpp
+++ b/src/xercesc/validators/common/DFAContentModel.cpp
@@ -38,6 +38,7 @@
#include <xercesc/validators/schema/SchemaSymbols.hpp>
#include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
#include <xercesc/validators/schema/XercesElementWildcard.hpp>
+#include <xercesc/util/OutOfMemoryException.hpp>
#include <xercesc/util/RefHashTableOf.hpp>
#include <xercesc/util/XMLInteger.hpp>
#include <math.h>
@@ -87,7 +88,15 @@ DFAContentModel::DFAContentModel( const bool dtd
, fMemoryManager(manager)
{
// And build the DFA data structures
- buildDFA(elemContentSpec);
+ try
+ {
+ buildDFA(elemContentSpec);
+ }
+ catch( const OutOfMemoryException& )
+ {
+ cleanup();
+ throw;
+ }
}
DFAContentModel::DFAContentModel( const bool dtd
@@ -115,37 +124,83 @@ DFAContentModel::DFAContentModel( const bool dtd
, fMemoryManager(manager)
{
// And build the DFA data structures
- buildDFA(elemContentSpec);
+ try
+ {
+ buildDFA(elemContentSpec);
+ }
+ catch( const OutOfMemoryException& )
+ {
+ cleanup();
+ throw;
+ }
}
DFAContentModel::~DFAContentModel()
{
+ cleanup();
+}
+
+void DFAContentModel::cleanup()
+{
//
// Clean up all the stuff that is not just temporary representation
// data that was cleaned up after building the DFA.
//
- fMemoryManager->deallocate(fFinalStateFlags); //delete [] fFinalStateFlags;
+ if( fFinalStateFlags )
+ {
+ fMemoryManager->deallocate(fFinalStateFlags); //delete [] fFinalStateFlags;
+ fFinalStateFlags = NULL;
+ }
unsigned int index;
- for (index = 0; index < fTransTableSize; index++)
- fMemoryManager->deallocate(fTransTable[index]); //delete [] fTransTable[index];
- fMemoryManager->deallocate(fTransTable); //delete [] fTransTable;
+ if( fTransTable )
+ {
+ for (index = 0; index < fTransTableSize; index++)
+ fMemoryManager->deallocate(fTransTable[index]); //delete [] fTransTable[index];
+ fMemoryManager->deallocate(fTransTable); //delete [] fTransTable;
+ fTransTable = NULL;
+ }
if(fCountingStates)
{
for (unsigned int j = 0; j < fTransTableSize; ++j)
delete fCountingStates[j];
fMemoryManager->deallocate(fCountingStates);
+ fCountingStates = NULL;
}
- for (index = 0; index < fLeafCount; index++)
- delete fElemMap[index];
- fMemoryManager->deallocate(fElemMap); //delete [] fElemMap;
+ if( fElemMap )
+ {
+ for (index = 0; index < fLeafCount; index++)
+ delete fElemMap[index];
+ fMemoryManager->deallocate(fElemMap); //delete [] fElemMap;
+ fElemMap = NULL;
+ }
fMemoryManager->deallocate(fElemMapType); //delete [] fElemMapType;
+ fElemMapType = NULL;
+
fMemoryManager->deallocate(fLeafListType); //delete [] fLeafListType;
+ fLeafListType = NULL;
delete fLeafNameTypeVector;
+ fLeafNameTypeVector = NULL;
+
+ // Cleanup things that might now have been clean up by buildDFA()
+ // if an exception occured.
+ if( fFollowList )
+ {
+ for (index = 0; index < fLeafCount; index++)
+ delete fFollowList[index];
+ fMemoryManager->deallocate(fFollowList); //delete [] fFollowList;
+ }
+
+ if( fLeafList )
+ {
+ for (index = 0; index < fLeafCount; index++)
+ delete fLeafList[index];
+ fMemoryManager->deallocate(fLeafList); //delete [] fLeafList;
+ }
}
@@ -612,6 +667,8 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
// leaf nodes. We will put them in the array according to their position values
//
fLeafList = (CMLeaf**) fMemoryManager->allocate(fLeafCount*sizeof(CMLeaf*)); //new CMLeaf*[fLeafCount];
+ memset(fLeafList, 0, fLeafCount*sizeof(CMLeaf*));
+
fLeafListType = (ContentSpecNode::NodeTypes*) fMemoryManager->allocate
(
fLeafCount * sizeof(ContentSpecNode::NodeTypes)
@@ -625,6 +682,7 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
(
fLeafCount * sizeof(CMStateSet*)
); //new CMStateSet*[fLeafCount];
+ memset(fLeafList, 0, fLeafCount*sizeof(CMStateSet*));
for (index = 0; index < fLeafCount; index++)
fFollowList[index] = new (fMemoryManager) CMStateSet(fLeafCount, fMemoryManager);
@@ -793,7 +851,7 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
**/
// don't forget to delete it
#ifdef OPTIMIZED_BUT_STILL_LINEAR_SEARCH
- int *fLeafSorter = (int*) fMemoryManager->allocate
+ int *leafSorter = (int*) fMemoryManager->allocate
(
(fLeafCount + fElemMapSize) * sizeof(int)
); //new int[fLeafCount + fElemMapSize];
@@ -811,23 +869,23 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
const QName* leaf = fLeafList[leafIndex]->getElement();
if (fDTD) {
if (XMLString::equals(leaf->getRawName(), elementRawName)) {
- fLeafSorter[fSortCount++] = leafIndex;
+ leafSorter[fSortCount++] = leafIndex;
}
}
else {
if ((fElemMapType[elemIndex] == fLeafListType[leafIndex]) &&
(leaf->getURI() == element->getURI()) &&
(XMLString::equals(leaf->getLocalPart(), element->getLocalPart()))) {
- fLeafSorter[fSortCount++] = leafIndex;
+ leafSorter[fSortCount++] = leafIndex;
}
}
}
- fLeafSorter[fSortCount++] = -1;
+ leafSorter[fSortCount++] = -1;
}
#endif
// instead of using a single array with -1 to separate elements, use a bidimensional map
- unsigned int** fLeafSorter = (unsigned int**)fMemoryManager->allocate(fElemMapSize * sizeof(unsigned int*));
+ unsigned int** leafSorter = (unsigned int**)fMemoryManager->allocate(fElemMapSize * sizeof(unsigned int*));
unsigned int* tmpSorter = (unsigned int*)fMemoryManager->allocate(fLeafCount * sizeof(unsigned int));
for (unsigned int elemIndex = 0; elemIndex < fElemMapSize; elemIndex++)
{
@@ -854,10 +912,10 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
}
}
- fLeafSorter[elemIndex]=(unsigned int*)fMemoryManager->allocate((fSortCount+1) * sizeof(unsigned int));
- fLeafSorter[elemIndex][0]=fSortCount;
+ leafSorter[elemIndex]=(unsigned int*)fMemoryManager->allocate((fSortCount+1) * sizeof(unsigned int));
+ leafSorter[elemIndex][0]=fSortCount;
for (unsigned int index=0;index<fSortCount;index++)
- fLeafSorter[elemIndex][index+1]=tmpSorter[index];
+ leafSorter[elemIndex][index+1]=tmpSorter[index];
}
fMemoryManager->deallocate(tmpSorter);
@@ -1015,7 +1073,7 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
#ifdef OPTIMIZED_BUT_STILL_LINEAR_SEARCH
// Optimization(Jan, 2001)
- int leafIndex = fLeafSorter[sorterIndex++];
+ int leafIndex = leafSorter[sorterIndex++];
while (leafIndex != -1)
{
@@ -1029,11 +1087,11 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
//
*newSet |= *fFollowList[leafIndex];
}
- leafIndex = fLeafSorter[sorterIndex++];
+ leafIndex = leafSorter[sorterIndex++];
} // while (leafIndex != -1)
#endif
- unsigned int* fLeafIndexes=fLeafSorter[elemIndex];
+ unsigned int* fLeafIndexes=leafSorter[elemIndex];
unsigned int fNumItems=fLeafIndexes[0];
if(fNumItems!=0)
{
@@ -1245,6 +1303,7 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
for (index = 0; index < fLeafCount; index++)
delete fFollowList[index];
fMemoryManager->deallocate(fFollowList); //delete [] fFollowList;
+ fFollowList = NULL;
//
// removeAll() will delete all data, XMLInteger,
@@ -1260,13 +1319,14 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
for (index = 0; index < fLeafCount; index++)
delete fLeafList[index];
fMemoryManager->deallocate(fLeafList); //delete [] fLeafList;
+ fLeafList = NULL;
#ifdef OPTIMIZED_BUT_STILL_LINEAR_SEARCH
- fMemoryManager->deallocate(fLeafSorter); //delete [] fLeafSorter;
+ fMemoryManager->deallocate(leafSorter); //delete [] leafSorter;
#endif
for (index=0; index < fElemMapSize; index++)
- fMemoryManager->deallocate(fLeafSorter[index]);
- fMemoryManager->deallocate(fLeafSorter);
+ fMemoryManager->deallocate(leafSorter[index]);
+ fMemoryManager->deallocate(leafSorter);
}
unsigned int DFAContentModel::countLeafNodes(ContentSpecNode* const curNode)
@@ -1369,13 +1429,21 @@ CMNode* DFAContentModel::buildSyntaxTree(ContentSpecNode* const curNode
, fLeafCount
, fMemoryManager
);
- fLeafList[curIndex] = new (fMemoryManager) CMLeaf
- (
- curNode->getElement()
- , curIndex
- , fLeafCount
- , fMemoryManager
- );
+ try
+ {
+ fLeafList[curIndex] = new (fMemoryManager) CMLeaf
+ (
+ curNode->getElement()
+ , curIndex
+ , fLeafCount
+ , fMemoryManager
+ );
+ }
+ catch( const OutOfMemoryException& )
+ {
+ delete retNode;
+ throw;
+ }
fLeafListType[curIndex] = ContentSpecNode::Leaf;
++curIndex;
}
@@ -1470,7 +1538,16 @@ CMNode* DFAContentModel::buildSyntaxTree(ContentSpecNode* const curNode
// same type as the source.
//
CMNode* newLeft = buildSyntaxTree(leftNode, curIndex);
- CMNode* newRight = buildSyntaxTree(rightNode, curIndex);
+ CMNode* newRight;
+ try
+ {
+ newRight = buildSyntaxTree(rightNode, curIndex);
+ }
+ catch( const OutOfMemoryException& )
+ {
+ delete newLeft;
+ throw;
+ }
if(((curType & 0x0f) == ContentSpecNode::Sequence))
{
//
@@ -1492,14 +1569,23 @@ CMNode* DFAContentModel::buildSyntaxTree(ContentSpecNode* const curNode
*fFollowList[index] |= first;
}
}
- retNode = new (fMemoryManager) CMBinaryOp
- (
- curType
- , newLeft
- , newRight
- , fLeafCount
- , fMemoryManager
- );
+ try
+ {
+ retNode = new (fMemoryManager) CMBinaryOp
+ (
+ curType
+ , newLeft
+ , newRight
+ , fLeafCount
+ , fMemoryManager
+ );
+ }
+ catch( const OutOfMemoryException& )
+ {
+ delete newLeft;
+ delete newRight;
+ throw;
+ }
}
else if (curType == ContentSpecNode::ZeroOrMore
|| curType == ContentSpecNode::ZeroOrOne
@@ -1543,9 +1629,17 @@ CMNode* DFAContentModel::buildSyntaxTree(ContentSpecNode* const curNode
}
}
// fault in the first and last pos, then delete it children
- retNode->getFirstPos();
- retNode->getLastPos();
- retNode->orphanChild();
+ try
+ {
+ retNode->getFirstPos();
+ retNode->getLastPos();
+ retNode->orphanChild();
+ }
+ catch( const OutOfMemoryException& )
+ {
+ delete retNode;
+ throw;
+ }
return retNode;
}
diff --git a/src/xercesc/validators/common/DFAContentModel.hpp b/src/xercesc/validators/common/DFAContentModel.hpp
index d0439d1..c6f9143 100644
--- a/src/xercesc/validators/common/DFAContentModel.hpp
+++ b/src/xercesc/validators/common/DFAContentModel.hpp
@@ -128,6 +128,7 @@ private :
// -----------------------------------------------------------------------
// Private helper methods
// -----------------------------------------------------------------------
+ void cleanup();
void buildDFA(ContentSpecNode* const curNode);
CMNode* buildSyntaxTree(ContentSpecNode* const curNode, unsigned int& curIndex);
unsigned int* makeDefStateList() const;
---------------------------------------------------------------------
To unsubscribe, e-mail: c-dev-unsubscribe@xerces.apache.org
For additional commands, e-mail: c-dev-help@xerces.apache.org