From e4d60a2d90b1ce2c2894b42e7df8fb2d5c48fb1f Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 2 Oct 2022 23:26:00 +0200 Subject: [PATCH] [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 ``` ame="x" type="xs:int" maxOccurs="1"/> ``` --- .../validators/common/DFAContentModel.cpp | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/xercesc/validators/common/DFAContentModel.cpp b/src/xercesc/validators/common/DFAContentModel.cpp index 856f88f46..45bbedf0b 100644 --- a/src/xercesc/validators/common/DFAContentModel.cpp +++ b/src/xercesc/validators/common/DFAContentModel.cpp @@ -42,6 +42,7 @@ #include #include #include +#include namespace XERCES_CPP_NAMESPACE { @@ -661,8 +662,15 @@ void DFAContentModel::buildDFA(ContentSpecNode* const curNode) // in the fLeafCount member. // fLeafCount=countLeafNodes(curNode); + // Avoid integer overflow in below fLeafCount++ increment + if (fLeafCount > std::numeric_limits::max() - 1) + throw OutOfMemoryException(); fEOCPos = fLeafCount++; + // Avoid integer overflow in below memory allocatoin + if (fLeafCount > std::numeric_limits::max() / sizeof(CMLeaf*)) + throw OutOfMemoryException(); + // We need to build an array of references to the non-epsilon // leaf nodes. We will put them in the array according to their position values // @@ -1364,14 +1372,27 @@ unsigned int DFAContentModel::countLeafNodes(ContentSpecNode* const curNode) if(nLoopCount!=0) { count += countLeafNodes(cursor); - for(unsigned int i=0;i std::numeric_limits::max() / nLoopCount) + throw OutOfMemoryException(); + const unsigned int countRightMulLoopCount = nLoopCount * countRight; + // Avoid integer overflow in below addition + if (count > std::numeric_limits::max() - countRightMulLoopCount) + throw OutOfMemoryException(); + count += countRightMulLoopCount; return count; } if(leftNode) count+=countLeafNodes(leftNode); if(rightNode) - count+=countLeafNodes(rightNode); + { + const unsigned int countRight = countLeafNodes(rightNode); + // Avoid integer overflow in below addition + if (count > std::numeric_limits::max() - countRight) + throw OutOfMemoryException(); + count+=countRight; + } } return count; }