diff options
author | Caolán McNamara <caolanm@redhat.com> | 2017-12-06 10:38:38 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2017-12-06 17:48:30 +0100 |
commit | 1a658831d86f6dba67f8f3bcd47435d496fe4dfa (patch) | |
tree | 88e4b2521e0deb7d81b41195ae45683b1d8580fc /starmath | |
parent | 495ac1bc97f3deea8e13cb1a2b9f59d087873c3f (diff) |
ofz#4539 depth protect mathtype parser
Change-Id: I46e12f52d56e7802b676309207904b4d1894d236
Reviewed-on: https://gerrit.libreoffice.org/45928
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'starmath')
-rw-r--r-- | starmath/inc/parse.hxx | 18 | ||||
-rw-r--r-- | starmath/source/mathmlimport.cxx | 17 | ||||
-rw-r--r-- | starmath/source/parse.cxx | 122 |
3 files changed, 150 insertions, 7 deletions
diff --git a/starmath/inc/parse.hxx b/starmath/inc/parse.hxx index 1bcef035d5b2..5d1eeef553d4 100644 --- a/starmath/inc/parse.hxx +++ b/starmath/inc/parse.hxx @@ -41,6 +41,24 @@ class SmParser m_nColOff; // 0-based bool m_bImportSymNames, m_bExportSymNames; + sal_Int32 m_nParseDepth; + + class DepthProtect + { + private: + sal_Int32& m_rParseDepth; + public: + DepthProtect(sal_Int32& rParseDepth) + : m_rParseDepth(rParseDepth) + { + ++m_rParseDepth; + } + bool TooDeep() const { return m_rParseDepth > 2048; } + ~DepthProtect() + { + --m_rParseDepth; + } + }; // map of used symbols (used to reduce file size by exporting only actually used symbols) std::set< OUString > m_aUsedSymbols; diff --git a/starmath/source/mathmlimport.cxx b/starmath/source/mathmlimport.cxx index 87befa6fdc85..3697f23b3c4d 100644 --- a/starmath/source/mathmlimport.cxx +++ b/starmath/source/mathmlimport.cxx @@ -297,11 +297,11 @@ ErrCode SmXMLImportWrapper::ReadThroughComponent( if ( pFilter && pFilter->GetSuccess() ) nError = ERRCODE_NONE; } - catch( xml::sax::SAXParseException& r ) + catch (const xml::sax::SAXParseException& r) { // sax parser sends wrapped exceptions, // try to find the original one - xml::sax::SAXException aSaxEx = *static_cast<xml::sax::SAXException*>(&r); + xml::sax::SAXException aSaxEx = *static_cast<const xml::sax::SAXException*>(&r); bool bTryChild = true; while( bTryChild ) @@ -320,7 +320,7 @@ ErrCode SmXMLImportWrapper::ReadThroughComponent( if ( bEncrypted ) nError = ERRCODE_SFX_WRONGPASSWORD; } - catch( const xml::sax::SAXException& r ) + catch (const xml::sax::SAXException& r) { packages::zip::ZipIOException aBrokenPackage; if ( r.WrappedException >>= aBrokenPackage ) @@ -329,11 +329,14 @@ ErrCode SmXMLImportWrapper::ReadThroughComponent( if ( bEncrypted ) nError = ERRCODE_SFX_WRONGPASSWORD; } - catch( packages::zip::ZipIOException& ) + catch (const packages::zip::ZipIOException&) { nError = ERRCODE_IO_BROKENPACKAGE; } - catch( io::IOException& ) + catch (const io::IOException&) + { + } + catch (const std::range_error&) { } @@ -3131,7 +3134,9 @@ extern "C" SAL_DLLPUBLIC_EXPORT bool SAL_CALL TestImportMML(SvStream &rStream) //to update the properties, which throws cause the properties are uninitialized xDocSh->SetLoading(SfxLoadedFlags::NONE); - auto nRet = SmXMLImportWrapper::ReadThroughComponent(xStream, xModel, xContext, xInfoSet, "com.sun.star.comp.Math.XMLImporter", false); + ErrCode nRet = ERRCODE_SFX_DOLOADFAILED; + + nRet = SmXMLImportWrapper::ReadThroughComponent(xStream, xModel, xContext, xInfoSet, "com.sun.star.comp.Math.XMLImporter", false); xDocSh->SetLoading(SfxLoadedFlags::ALL); diff --git a/starmath/source/parse.cxx b/starmath/source/parse.cxx index b920fc871130..92dca7b025a1 100644 --- a/starmath/source/parse.cxx +++ b/starmath/source/parse.cxx @@ -940,6 +940,10 @@ void SmParser::NextToken() SmTableNode *SmParser::DoTable() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + SmNodeArray aLineArray; aLineArray.push_back(DoLine()); while (m_aCurToken.eType == TNEWLINE) @@ -956,6 +960,10 @@ SmTableNode *SmParser::DoTable() SmNode *SmParser::DoAlign(bool bUseExtraSpaces) // parse alignment info (if any), then go on with rest of expression { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + std::unique_ptr<SmStructureNode> pSNode; if (TokenInGroup(TG::Align)) @@ -982,6 +990,10 @@ SmNode *SmParser::DoAlign(bool bUseExtraSpaces) // Postcondition: m_aCurToken.eType == TEND || m_aCurToken.eType == TNEWLINE SmLineNode *SmParser::DoLine() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + SmNodeArray ExpressionArray; // start with single expression that may have an alignment statement @@ -1010,6 +1022,10 @@ SmLineNode *SmParser::DoLine() SmNode *SmParser::DoExpression(bool bUseExtraSpaces) { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + SmNodeArray RelationArray; RelationArray.push_back(DoRelation()); while (m_aCurToken.nLevel >= 4) @@ -1031,6 +1047,10 @@ SmNode *SmParser::DoExpression(bool bUseExtraSpaces) SmNode *SmParser::DoRelation() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + SmNode *pFirst = DoSum(); while (TokenInGroup(TG::Relation)) { @@ -1045,6 +1065,10 @@ SmNode *SmParser::DoRelation() SmNode *SmParser::DoSum() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + SmNode *pFirst = DoProduct(); while (TokenInGroup(TG::Sum)) { @@ -1059,6 +1083,10 @@ SmNode *SmParser::DoSum() SmNode *SmParser::DoProduct() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + SmNode *pFirst = DoPower(); while (TokenInGroup(TG::Product)) @@ -1132,6 +1160,10 @@ SmNode *SmParser::DoProduct() SmNode *SmParser::DoSubSup(TG nActiveGroup, SmNode *pGivenNode) { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + assert(nActiveGroup == TG::Power || nActiveGroup == TG::Limit); assert(m_aCurToken.nGroup == nActiveGroup); @@ -1202,6 +1234,10 @@ SmNode *SmParser::DoSubSup(TG nActiveGroup, SmNode *pGivenNode) SmNode *SmParser::DoOpSubSup() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + // get operator symbol auto pNode = o3tl::make_unique<SmMathSymbolNode>(m_aCurToken); // skip operator token @@ -1214,6 +1250,10 @@ SmNode *SmParser::DoOpSubSup() SmNode *SmParser::DoPower() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + // get body for sub- supscripts on top of stack SmNode *pNode = DoTerm(false); @@ -1224,6 +1264,10 @@ SmNode *SmParser::DoPower() SmBlankNode *SmParser::DoBlank() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + assert(TokenInGroup(TG::Blank)); std::unique_ptr<SmBlankNode> pBlankNode(new SmBlankNode(m_aCurToken)); @@ -1245,6 +1289,10 @@ SmBlankNode *SmParser::DoBlank() SmNode *SmParser::DoTerm(bool bGroupNumberIdent) { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + switch (m_aCurToken.eType) { case TESCAPE : @@ -1454,6 +1502,10 @@ SmNode *SmParser::DoTerm(bool bGroupNumberIdent) SmNode *SmParser::DoEscape() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + NextToken(); switch (m_aCurToken.eType) @@ -1490,6 +1542,10 @@ SmNode *SmParser::DoEscape() SmOperNode *SmParser::DoOperator() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + assert(TokenInGroup(TG::Oper)); auto pSNode = o3tl::make_unique<SmOperNode>(m_aCurToken); @@ -1510,6 +1566,10 @@ SmOperNode *SmParser::DoOperator() SmNode *SmParser::DoOper() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + SmTokenType eType (m_aCurToken.eType); std::unique_ptr<SmNode> pNode; @@ -1564,6 +1624,10 @@ SmNode *SmParser::DoOper() SmStructureNode *SmParser::DoUnOper() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + assert(TokenInGroup(TG::UnOper)); SmToken aNodeToken = m_aCurToken; @@ -1649,6 +1713,10 @@ SmStructureNode *SmParser::DoUnOper() SmAttributNode *SmParser::DoAttribut() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + assert(TokenInGroup(TG::Attribute)); auto pSNode = o3tl::make_unique<SmAttributNode>(m_aCurToken); @@ -1682,9 +1750,12 @@ SmAttributNode *SmParser::DoAttribut() return pSNode.release(); } - SmStructureNode *SmParser::DoFontAttribut() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + assert(TokenInGroup(TG::FontAttr)); switch (m_aCurToken.eType) @@ -1717,6 +1788,10 @@ SmStructureNode *SmParser::DoFontAttribut() SmStructureNode *SmParser::DoColor() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + assert(m_aCurToken.eType == TCOLOR); // last color rules, get that one @@ -1737,6 +1812,10 @@ SmStructureNode *SmParser::DoColor() SmStructureNode *SmParser::DoFont() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + assert(m_aCurToken.eType == TFONT); // last font rules, get that one @@ -1780,6 +1859,10 @@ static bool lcl_IsNumber(const OUString& rText) SmStructureNode *SmParser::DoFontSize() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + assert(m_aCurToken.eType == TSIZE); FontSizeType Type; @@ -1842,6 +1925,10 @@ SmStructureNode *SmParser::DoFontSize() SmStructureNode *SmParser::DoBrace() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + assert(m_aCurToken.eType == TLEFT || TokenInGroup(TG::LBrace)); std::unique_ptr<SmStructureNode> pSNode(new SmBraceNode(m_aCurToken)); @@ -1926,6 +2013,10 @@ SmStructureNode *SmParser::DoBrace() SmBracebodyNode *SmParser::DoBracebody(bool bIsLeftRight) { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + auto pBody = o3tl::make_unique<SmBracebodyNode>(m_aCurToken); SmNodeArray aNodes; // get body if any @@ -1971,6 +2062,10 @@ SmBracebodyNode *SmParser::DoBracebody(bool bIsLeftRight) SmTextNode *SmParser::DoFunction() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + switch (m_aCurToken.eType) { case TFUNC: @@ -2010,6 +2105,10 @@ SmTextNode *SmParser::DoFunction() SmTableNode *SmParser::DoBinom() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + auto pSNode = o3tl::make_unique<SmTableNode>(m_aCurToken); NextToken(); @@ -2022,6 +2121,10 @@ SmTableNode *SmParser::DoBinom() SmStructureNode *SmParser::DoStack() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + std::unique_ptr<SmStructureNode> pSNode(new SmTableNode(m_aCurToken)); NextToken(); if (m_aCurToken.eType != TLGROUP) @@ -2045,6 +2148,10 @@ SmStructureNode *SmParser::DoStack() SmStructureNode *SmParser::DoMatrix() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + std::unique_ptr<SmMatrixNode> pMNode(new SmMatrixNode(m_aCurToken)); NextToken(); if (m_aCurToken.eType != TLGROUP) @@ -2101,6 +2208,10 @@ SmStructureNode *SmParser::DoMatrix() SmSpecialNode *SmParser::DoSpecial() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + bool bReplace = false; OUString &rName = m_aCurToken.aText; OUString aNewName; @@ -2143,6 +2254,10 @@ SmSpecialNode *SmParser::DoSpecial() SmGlyphSpecialNode *SmParser::DoGlyphSpecial() { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + auto pNode = o3tl::make_unique<SmGlyphSpecialNode>(m_aCurToken); NextToken(); return pNode.release(); @@ -2150,6 +2265,10 @@ SmGlyphSpecialNode *SmParser::DoGlyphSpecial() SmExpressionNode *SmParser::DoError(SmParseError eError) { + DepthProtect aDepthGuard(m_nParseDepth); + if (aDepthGuard.TooDeep()) + throw std::range_error("parser depth limit"); + auto pSNode = o3tl::make_unique<SmExpressionNode>(m_aCurToken); SmErrorNode *pErr = new SmErrorNode(m_aCurToken); pSNode->SetSubNodes(pErr, nullptr); @@ -2172,6 +2291,7 @@ SmParser::SmParser() , m_nColOff( 0 ) , m_bImportSymNames( false ) , m_bExportSymNames( false ) + , m_nParseDepth(0) , m_aNumCC( LanguageTag( LANGUAGE_ENGLISH_US ) ) , m_pSysCC( SM_MOD()->GetSysLocale().GetCharClassPtr() ) { |