Skip to content

Commit

Permalink
DFAContentModel::buildDFA(): fix memory leaks when OutOfMemoryExcepti…
Browse files Browse the repository at this point in the history
  • Loading branch information
rouault committed Dec 4, 2021
1 parent 8ac9637 commit f7e7633
Showing 1 changed file with 67 additions and 25 deletions.
92 changes: 67 additions & 25 deletions src/xercesc/validators/common/DFAContentModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ void DFAContentModel::cleanup()
delete fLeafList[index];
fMemoryManager->deallocate(fLeafList); //delete [] fLeafList;
}

delete fHeadNode;
}


Expand Down Expand Up @@ -674,6 +676,7 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
fLeafCount * sizeof(ContentSpecNode::NodeTypes)
); //new ContentSpecNode::NodeTypes[fLeafCount];
//
memset(fLeafListType, 0, fLeafCount*sizeof(ContentSpecNode::NodeTypes));
// And, moving onward... We now need to build the follow position sets
// for all the nodes. So we allocate an array of pointers to state sets,
// one for each leaf node (i.e. each significant DFA position.)
Expand Down Expand Up @@ -780,10 +783,12 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
(
fLeafCount * sizeof(QName*)
); //new QName*[fLeafCount];
memset(fElemMap, 0, fLeafCount * sizeof(QName*));
fElemMapType = (ContentSpecNode::NodeTypes*) fMemoryManager->allocate
(
fLeafCount * sizeof(ContentSpecNode::NodeTypes)
); //new ContentSpecNode::NodeTypes[fLeafCount];
memset(fElemMapType, 0, fLeafCount * sizeof(ContentSpecNode::NodeTypes));
fElemMapSize = 0;

Occurence** elemOccurenceMap=0;
Expand Down Expand Up @@ -962,6 +967,7 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
//

delete fHeadNode;
fHeadNode = nullptr;

//
// Init our two state flags. Basically the unmarked state counter is
Expand Down Expand Up @@ -1003,6 +1009,12 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
// the states to do counter.
//
CMStateSet* newSet = 0;

// Store potential OutOfMemoryException caught in the loop, to
// be able to perform cleanup first, and rethrow it afterwards.
OutOfMemoryException oomException;
bool gotOomException = false;

while (unmarkedState < curState)
{
//
Expand Down Expand Up @@ -1191,12 +1203,21 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
// table.
//
statesToDo[curState] = newSet;
fTransTable[curState] = makeDefStateList();
stateTable->put
(
newSet
, new (fMemoryManager) XMLInteger(curState)
);
try
{
fTransTable[curState] = makeDefStateList();
stateTable->put
(
newSet
, new (fMemoryManager) XMLInteger(curState)
);
}
catch( const OutOfMemoryException& e )
{
oomException = e;
gotOomException = true;
goto after_loop;
}

// We now have a new state to do so bump the count
curState++;
Expand Down Expand Up @@ -1225,27 +1246,43 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
// size by 50% and allocate new arrays.
//
const unsigned int newSize = (unsigned int)(curArraySize * 1.5);
CMStateSet** newToDo = (CMStateSet**)
fMemoryManager->allocate
(
newSize * sizeof(CMStateSet*)
); //new const CMStateSet*[newSize];
bool* newFinalFlags = (bool*) fMemoryManager->allocate
(
newSize * sizeof(bool)
); //new bool[newSize];
unsigned int** newTransTable = (unsigned int**)
fMemoryManager->allocate
CMStateSet** newToDo = nullptr;
bool* newFinalFlags = nullptr;
unsigned int** newTransTable = nullptr;
try
{
newToDo = (CMStateSet**)
fMemoryManager->allocate
(
newSize * sizeof(CMStateSet*)
); //new const CMStateSet*[newSize];
newFinalFlags = (bool*) fMemoryManager->allocate
(
newSize * sizeof(unsigned int*)
); //new unsigned int*[newSize];

// Copy over all of the existing content
for (unsigned int expIndex = 0; expIndex < curArraySize; expIndex++)
newSize * sizeof(bool)
); //new bool[newSize];
newTransTable = (unsigned int**)
fMemoryManager->allocate
(
newSize * sizeof(unsigned int*)
); //new unsigned int*[newSize];

// Copy over all of the existing content
for (unsigned int expIndex = 0; expIndex < curArraySize; expIndex++)
{
newToDo[expIndex] = statesToDo[expIndex];
newFinalFlags[expIndex] = fFinalStateFlags[expIndex];
newTransTable[expIndex] = fTransTable[expIndex];
}
}
catch( const OutOfMemoryException& e )
{
newToDo[expIndex] = statesToDo[expIndex];
newFinalFlags[expIndex] = fFinalStateFlags[expIndex];
newTransTable[expIndex] = fTransTable[expIndex];
oomException = e;
gotOomException = true;
fMemoryManager->deallocate(newToDo);
fMemoryManager->deallocate(newFinalFlags);
fMemoryManager->deallocate(newTransTable);
goto after_loop;

}

// Clean up the old stuff
Expand All @@ -1263,6 +1300,8 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
} // for elemIndex
} //while

after_loop:

// Store the current state count in the trans table size
fTransTableSize = curState;

Expand Down Expand Up @@ -1327,6 +1366,9 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
for (index=0; index < fElemMapSize; index++)
fMemoryManager->deallocate(leafSorter[index]);
fMemoryManager->deallocate(leafSorter);

if (gotOomException)
throw oomException;
}

unsigned int DFAContentModel::countLeafNodes(ContentSpecNode* const curNode)
Expand Down

0 comments on commit f7e7633

Please sign in to comment.