diff options
-rw-r--r-- | xfa/fxfa/fm2js/cxfa_fmparser.cpp | 74 | ||||
-rw-r--r-- | xfa/fxfa/fm2js/cxfa_fmparser.h | 7 | ||||
-rw-r--r-- | xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp | 7 |
3 files changed, 63 insertions, 25 deletions
diff --git a/xfa/fxfa/fm2js/cxfa_fmparser.cpp b/xfa/fxfa/fm2js/cxfa_fmparser.cpp index 4cd9a747a9..42a65e5838 100644 --- a/xfa/fxfa/fm2js/cxfa_fmparser.cpp +++ b/xfa/fxfa/fm2js/cxfa_fmparser.cpp @@ -14,12 +14,13 @@ namespace { -const int kMaxAssignmentChainLength = 12; +const unsigned int kMaxAssignmentChainLength = 12; +const unsigned int kMaxParseDepth = 2000; } // namespace CXFA_FMParser::CXFA_FMParser(const CFX_WideStringC& wsFormcalc) - : m_error(false) { + : m_error(false), m_parse_depth(0), m_max_parse_depth(kMaxParseDepth) { m_lexer = pdfium::MakeUnique<CXFA_FMLexer>(wsFormcalc); m_token = m_lexer->NextToken(); } @@ -56,13 +57,18 @@ bool CXFA_FMParser::CheckThenNext(XFA_FM_TOKEN op) { return NextToken(); } +bool CXFA_FMParser::IncrementParseDepthAndCheck() { + return ++m_parse_depth < m_max_parse_depth; +} + std::vector<std::unique_ptr<CXFA_FMExpression>> CXFA_FMParser::ParseTopExpression() { + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return std::vector<std::unique_ptr<CXFA_FMExpression>>(); + std::unique_ptr<CXFA_FMExpression> expr; std::vector<std::unique_ptr<CXFA_FMExpression>> expressions; - if (HasError()) - return expressions; - while (!HasError()) { if (m_token->m_type == TOKeof || m_token->m_type == TOKendfunc || m_token->m_type == TOKendif || m_token->m_type == TOKelseif || @@ -73,18 +79,16 @@ CXFA_FMParser::ParseTopExpression() { expr = m_token->m_type == TOKfunc ? ParseFunction() : ParseExpression(); if (!expr) { m_error = true; - expressions.clear(); break; } expressions.push_back(std::move(expr)); } - if (HasError()) - expressions.clear(); - return expressions; + return std::vector<std::unique_ptr<CXFA_FMExpression>>(); } std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseFunction() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; CFX_WideStringC ident; @@ -146,7 +150,8 @@ std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseFunction() { } std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; std::unique_ptr<CXFA_FMExpression> expr; @@ -198,7 +203,8 @@ std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseExpression() { } std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseVarExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; CFX_WideStringC ident; @@ -254,7 +260,8 @@ CXFA_FMParser::ParseSimpleExpression() { } std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseExpExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; @@ -266,7 +273,8 @@ std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseExpExpression() { std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseLogicalOrExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; @@ -300,7 +308,8 @@ CXFA_FMParser::ParseLogicalOrExpression() { std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseLogicalAndExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; @@ -333,7 +342,8 @@ CXFA_FMParser::ParseLogicalAndExpression() { std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseEqualityExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; @@ -377,7 +387,8 @@ CXFA_FMParser::ParseEqualityExpression() { std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseRelationalExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; @@ -446,7 +457,8 @@ CXFA_FMParser::ParseRelationalExpression() { std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseAddtiveExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; @@ -489,7 +501,8 @@ CXFA_FMParser::ParseAddtiveExpression() { std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseMultiplicativeExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; @@ -531,7 +544,8 @@ CXFA_FMParser::ParseMultiplicativeExpression() { } std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseUnaryExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; std::unique_ptr<CXFA_FMSimpleExpression> expr; @@ -578,7 +592,8 @@ std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseUnaryExpression() { std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParsePrimaryExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; std::unique_ptr<CXFA_FMSimpleExpression> expr; @@ -661,6 +676,7 @@ std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParsePostExpression( ParseSimpleExpression(); if (!simple_expr) return nullptr; + expressions.push_back(std::move(simple_expr)); if (m_token->m_type == TOKcomma) { if (!NextToken()) @@ -834,7 +850,8 @@ std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParsePostExpression( } std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseIndexExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; @@ -876,6 +893,10 @@ std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseIndexExpression() { } std::unique_ptr<CXFA_FMSimpleExpression> CXFA_FMParser::ParseParenExpression() { + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) + return nullptr; + if (!CheckThenNext(TOKlparen)) return nullptr; @@ -951,7 +972,8 @@ std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseBlockExpression() { } std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseIfExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; @@ -1021,7 +1043,8 @@ std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseIfExpression() { } std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseWhileExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; uint32_t line = m_token->m_line_num; @@ -1055,7 +1078,8 @@ CXFA_FMParser::ParseSubassignmentInForExpression() { } std::unique_ptr<CXFA_FMExpression> CXFA_FMParser::ParseForExpression() { - if (HasError()) + CFX_AutoRestorer<unsigned long> restorer(&m_parse_depth); + if (HasError() || !IncrementParseDepthAndCheck()) return nullptr; CFX_WideStringC wsVariant; diff --git a/xfa/fxfa/fm2js/cxfa_fmparser.h b/xfa/fxfa/fm2js/cxfa_fmparser.h index 66eb1f8392..ddfaa1aaa6 100644 --- a/xfa/fxfa/fm2js/cxfa_fmparser.h +++ b/xfa/fxfa/fm2js/cxfa_fmparser.h @@ -21,9 +21,14 @@ class CXFA_FMParser { std::unique_ptr<CXFA_FMFunctionDefinition> Parse(); bool HasError() const; + void SetMaxParseDepthForTest(unsigned long max_depth) { + m_max_parse_depth = max_depth; + } + private: bool NextToken(); bool CheckThenNext(XFA_FM_TOKEN op); + bool IncrementParseDepthAndCheck(); std::vector<std::unique_ptr<CXFA_FMExpression>> ParseTopExpression(); std::unique_ptr<CXFA_FMExpression> ParseFunction(); @@ -54,6 +59,8 @@ class CXFA_FMParser { std::unique_ptr<CXFA_FMLexer> m_lexer; std::unique_ptr<CXFA_FMToken> m_token; bool m_error; + unsigned long m_parse_depth; + unsigned long m_max_parse_depth; }; #endif // XFA_FXFA_FM2JS_CXFA_FMPARSER_H_ diff --git a/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp b/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp index 9907890e83..214fd4aec3 100644 --- a/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp +++ b/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp @@ -107,3 +107,10 @@ TEST(CXFA_FMParserTest, Parse) { EXPECT_TRUE(ast->ToJavaScript(buf)); EXPECT_EQ(ret, buf.AsStringC()); } + +TEST(CXFA_FMParserTest, MaxParseDepth) { + auto parser = pdfium::MakeUnique<CXFA_FMParser>(L"foo(bar[baz(fizz[0])])"); + parser->SetMaxParseDepthForTest(5); + EXPECT_EQ(nullptr, parser->Parse()); + EXPECT_TRUE(parser->HasError()); +} |