Skip to content

Commit f7e7633

Browse files
committed
DFAContentModel::buildDFA(): fix memory leaks when OutOfMemoryException occurs
Fixes GDAL's https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=41335
1 parent 8ac9637 commit f7e7633

File tree

1 file changed

+67
-25
lines changed

1 file changed

+67
-25
lines changed

src/xercesc/validators/common/DFAContentModel.cpp

Lines changed: 67 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ void DFAContentModel::cleanup()
201201
delete fLeafList[index];
202202
fMemoryManager->deallocate(fLeafList); //delete [] fLeafList;
203203
}
204+
205+
delete fHeadNode;
204206
}
205207

206208

@@ -674,6 +676,7 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
674676
fLeafCount * sizeof(ContentSpecNode::NodeTypes)
675677
); //new ContentSpecNode::NodeTypes[fLeafCount];
676678
//
679+
memset(fLeafListType, 0, fLeafCount*sizeof(ContentSpecNode::NodeTypes));
677680
// And, moving onward... We now need to build the follow position sets
678681
// for all the nodes. So we allocate an array of pointers to state sets,
679682
// one for each leaf node (i.e. each significant DFA position.)
@@ -780,10 +783,12 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
780783
(
781784
fLeafCount * sizeof(QName*)
782785
); //new QName*[fLeafCount];
786+
memset(fElemMap, 0, fLeafCount * sizeof(QName*));
783787
fElemMapType = (ContentSpecNode::NodeTypes*) fMemoryManager->allocate
784788
(
785789
fLeafCount * sizeof(ContentSpecNode::NodeTypes)
786790
); //new ContentSpecNode::NodeTypes[fLeafCount];
791+
memset(fElemMapType, 0, fLeafCount * sizeof(ContentSpecNode::NodeTypes));
787792
fElemMapSize = 0;
788793

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

964969
delete fHeadNode;
970+
fHeadNode = nullptr;
965971

966972
//
967973
// Init our two state flags. Basically the unmarked state counter is
@@ -1003,6 +1009,12 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
10031009
// the states to do counter.
10041010
//
10051011
CMStateSet* newSet = 0;
1012+
1013+
// Store potential OutOfMemoryException caught in the loop, to
1014+
// be able to perform cleanup first, and rethrow it afterwards.
1015+
OutOfMemoryException oomException;
1016+
bool gotOomException = false;
1017+
10061018
while (unmarkedState < curState)
10071019
{
10081020
//
@@ -1191,12 +1203,21 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
11911203
// table.
11921204
//
11931205
statesToDo[curState] = newSet;
1194-
fTransTable[curState] = makeDefStateList();
1195-
stateTable->put
1196-
(
1197-
newSet
1198-
, new (fMemoryManager) XMLInteger(curState)
1199-
);
1206+
try
1207+
{
1208+
fTransTable[curState] = makeDefStateList();
1209+
stateTable->put
1210+
(
1211+
newSet
1212+
, new (fMemoryManager) XMLInteger(curState)
1213+
);
1214+
}
1215+
catch( const OutOfMemoryException& e )
1216+
{
1217+
oomException = e;
1218+
gotOomException = true;
1219+
goto after_loop;
1220+
}
12001221

12011222
// We now have a new state to do so bump the count
12021223
curState++;
@@ -1225,27 +1246,43 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
12251246
// size by 50% and allocate new arrays.
12261247
//
12271248
const unsigned int newSize = (unsigned int)(curArraySize * 1.5);
1228-
CMStateSet** newToDo = (CMStateSet**)
1229-
fMemoryManager->allocate
1230-
(
1231-
newSize * sizeof(CMStateSet*)
1232-
); //new const CMStateSet*[newSize];
1233-
bool* newFinalFlags = (bool*) fMemoryManager->allocate
1234-
(
1235-
newSize * sizeof(bool)
1236-
); //new bool[newSize];
1237-
unsigned int** newTransTable = (unsigned int**)
1238-
fMemoryManager->allocate
1249+
CMStateSet** newToDo = nullptr;
1250+
bool* newFinalFlags = nullptr;
1251+
unsigned int** newTransTable = nullptr;
1252+
try
1253+
{
1254+
newToDo = (CMStateSet**)
1255+
fMemoryManager->allocate
1256+
(
1257+
newSize * sizeof(CMStateSet*)
1258+
); //new const CMStateSet*[newSize];
1259+
newFinalFlags = (bool*) fMemoryManager->allocate
12391260
(
1240-
newSize * sizeof(unsigned int*)
1241-
); //new unsigned int*[newSize];
1242-
1243-
// Copy over all of the existing content
1244-
for (unsigned int expIndex = 0; expIndex < curArraySize; expIndex++)
1261+
newSize * sizeof(bool)
1262+
); //new bool[newSize];
1263+
newTransTable = (unsigned int**)
1264+
fMemoryManager->allocate
1265+
(
1266+
newSize * sizeof(unsigned int*)
1267+
); //new unsigned int*[newSize];
1268+
1269+
// Copy over all of the existing content
1270+
for (unsigned int expIndex = 0; expIndex < curArraySize; expIndex++)
1271+
{
1272+
newToDo[expIndex] = statesToDo[expIndex];
1273+
newFinalFlags[expIndex] = fFinalStateFlags[expIndex];
1274+
newTransTable[expIndex] = fTransTable[expIndex];
1275+
}
1276+
}
1277+
catch( const OutOfMemoryException& e )
12451278
{
1246-
newToDo[expIndex] = statesToDo[expIndex];
1247-
newFinalFlags[expIndex] = fFinalStateFlags[expIndex];
1248-
newTransTable[expIndex] = fTransTable[expIndex];
1279+
oomException = e;
1280+
gotOomException = true;
1281+
fMemoryManager->deallocate(newToDo);
1282+
fMemoryManager->deallocate(newFinalFlags);
1283+
fMemoryManager->deallocate(newTransTable);
1284+
goto after_loop;
1285+
12491286
}
12501287

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

1303+
after_loop:
1304+
12661305
// Store the current state count in the trans table size
12671306
fTransTableSize = curState;
12681307

@@ -1327,6 +1366,9 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
13271366
for (index=0; index < fElemMapSize; index++)
13281367
fMemoryManager->deallocate(leafSorter[index]);
13291368
fMemoryManager->deallocate(leafSorter);
1369+
1370+
if (gotOomException)
1371+
throw oomException;
13301372
}
13311373

13321374
unsigned int DFAContentModel::countLeafNodes(ContentSpecNode* const curNode)

0 commit comments

Comments
 (0)