Skip to content

Commit e4d60a2

Browse files
committed
[XERCESC-2241] Fix integer overflows in DFAContentModel class
On .xsd files like the following ones (generated by ossfuzz, so broken), integer overflows can happen in DFAContentModel::countLeafNodes() and DFAContentModel::buildDFA() which can later cause out-of-bounds access. Found in https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=52025 ``` <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:myns="http://myns" targetNamespace="http://myns" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:element name="main_elt"> <xs:complexType> <xs:sequence> <xs:group ref="myns:mygroup" minOccurs="32767" maxOccurs="1"/> </xs:sequence> </xs:complexType> </xs:element> <xs:group name="mygroup"> <xs:sequence> <!-- related to https://issues.apache.org/jira/browse/XERCESC-1051 --> <xs:element name="elt" maxOccurs="33333"> <xs:complexType> <xs:sequence> ame="x" type="xs:int" maxOccurs="1"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> </xs:group> </xs:schema> ```
1 parent 045bdf8 commit e4d60a2

File tree

1 file changed

+24
-3
lines changed

1 file changed

+24
-3
lines changed

src/xercesc/validators/common/DFAContentModel.cpp

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <xercesc/util/RefHashTableOf.hpp>
4343
#include <xercesc/util/XMLInteger.hpp>
4444
#include <math.h>
45+
#include <limits>
4546

4647
namespace XERCES_CPP_NAMESPACE {
4748

@@ -661,8 +662,15 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode)
661662
// in the fLeafCount member.
662663
//
663664
fLeafCount=countLeafNodes(curNode);
665+
// Avoid integer overflow in below fLeafCount++ increment
666+
if (fLeafCount > std::numeric_limits<unsigned int>::max() - 1)
667+
throw OutOfMemoryException();
664668
fEOCPos = fLeafCount++;
665669

670+
// Avoid integer overflow in below memory allocatoin
671+
if (fLeafCount > std::numeric_limits<size_t>::max() / sizeof(CMLeaf*))
672+
throw OutOfMemoryException();
673+
666674
// We need to build an array of references to the non-epsilon
667675
// leaf nodes. We will put them in the array according to their position values
668676
//
@@ -1364,14 +1372,27 @@ unsigned int DFAContentModel::countLeafNodes(ContentSpecNode* const curNode)
13641372
if(nLoopCount!=0)
13651373
{
13661374
count += countLeafNodes(cursor);
1367-
for(unsigned int i=0;i<nLoopCount;i++)
1368-
count += countLeafNodes(rightNode);
1375+
const unsigned int countRight = countLeafNodes(rightNode);
1376+
// Avoid integer overflow in below multiplication
1377+
if (countRight > std::numeric_limits<unsigned int>::max() / nLoopCount)
1378+
throw OutOfMemoryException();
1379+
const unsigned int countRightMulLoopCount = nLoopCount * countRight;
1380+
// Avoid integer overflow in below addition
1381+
if (count > std::numeric_limits<unsigned int>::max() - countRightMulLoopCount)
1382+
throw OutOfMemoryException();
1383+
count += countRightMulLoopCount;
13691384
return count;
13701385
}
13711386
if(leftNode)
13721387
count+=countLeafNodes(leftNode);
13731388
if(rightNode)
1374-
count+=countLeafNodes(rightNode);
1389+
{
1390+
const unsigned int countRight = countLeafNodes(rightNode);
1391+
// Avoid integer overflow in below addition
1392+
if (count > std::numeric_limits<unsigned int>::max() - countRight)
1393+
throw OutOfMemoryException();
1394+
count+=countRight;
1395+
}
13751396
}
13761397
return count;
13771398
}

0 commit comments

Comments
 (0)