diff options
-rw-r--r-- | xfa/fxfa/fm2js/xfa_error.cpp | 1 | ||||
-rw-r--r-- | xfa/fxfa/fm2js/xfa_error.h | 1 | ||||
-rw-r--r-- | xfa/fxfa/fm2js/xfa_lexer.cpp | 89 | ||||
-rw-r--r-- | xfa/fxfa/fm2js/xfa_lexer.h | 1 |
4 files changed, 84 insertions, 8 deletions
diff --git a/xfa/fxfa/fm2js/xfa_error.cpp b/xfa/fxfa/fm2js/xfa_error.cpp index 1d31ce6958..ea0511a89a 100644 --- a/xfa/fxfa/fm2js/xfa_error.cpp +++ b/xfa/fxfa/fm2js/xfa_error.cpp @@ -17,3 +17,4 @@ const wchar_t kFMErrExpectedNonEmptyExpression[] = L"expected non-empty expression"; const wchar_t kFMErrLongAssignmentChain[] = L"long assignment chains are unsupported"; +const wchar_t kFMErrEndOfInput[] = L"unexpected end of input"; diff --git a/xfa/fxfa/fm2js/xfa_error.h b/xfa/fxfa/fm2js/xfa_error.h index b6621da440..27ed1879cf 100644 --- a/xfa/fxfa/fm2js/xfa_error.h +++ b/xfa/fxfa/fm2js/xfa_error.h @@ -18,6 +18,7 @@ extern const wchar_t kFMErrExpectedEndIf[]; extern const wchar_t kFMErrUnexpectedExpression[]; extern const wchar_t kFMErrExpectedNonEmptyExpression[]; extern const wchar_t kFMErrLongAssignmentChain[]; +extern const wchar_t kFMErrEndOfInput[]; class CXFA_FMErrorInfo { public: diff --git a/xfa/fxfa/fm2js/xfa_lexer.cpp b/xfa/fxfa/fm2js/xfa_lexer.cpp index 069c32f028..dfac51ab2c 100644 --- a/xfa/fxfa/fm2js/xfa_lexer.cpp +++ b/xfa/fxfa/fm2js/xfa_lexer.cpp @@ -96,12 +96,21 @@ CXFA_FMToken::CXFA_FMToken(uint32_t uLineNum) CXFA_FMLexer::CXFA_FMLexer(const CFX_WideStringC& wsFormCalc, CXFA_FMErrorInfo* pErrorInfo) - : m_ptr(wsFormCalc.c_str()), m_uCurrentLine(1), m_pErrorInfo(pErrorInfo) {} + : m_ptr(wsFormCalc.c_str()), + m_end(m_ptr + wsFormCalc.GetLength() - 1), + m_uCurrentLine(1), + m_pErrorInfo(pErrorInfo) {} CXFA_FMLexer::~CXFA_FMLexer() {} CXFA_FMToken* CXFA_FMLexer::NextToken() { - m_pToken = Scan(); + // Make sure we don't walk off the end of the string. + if (m_ptr > m_end) { + m_pToken = pdfium::MakeUnique<CXFA_FMToken>(m_uCurrentLine); + m_pToken->m_type = TOKeof; + } else { + m_pToken = Scan(); + } return m_pToken.get(); } @@ -115,6 +124,10 @@ std::unique_ptr<CXFA_FMToken> CXFA_FMLexer::Scan() { } while (1) { + // Make sure we don't walk off the end of the string. + if (m_ptr > m_end) + return p; + ch = *m_ptr; if (!IsValid(m_ptr)) { Error(kFMErrUnsupportedChar, ch); @@ -158,6 +171,11 @@ std::unique_ptr<CXFA_FMToken> CXFA_FMLexer::Scan() { } case '=': ++m_ptr; + if (m_ptr > m_end) { + Error(kFMErrEndOfInput); + return p; + } + if (IsValid(m_ptr)) { ch = *m_ptr; if (ch == '=') { @@ -173,6 +191,11 @@ std::unique_ptr<CXFA_FMToken> CXFA_FMLexer::Scan() { return p; case '<': ++m_ptr; + if (m_ptr > m_end) { + Error(kFMErrEndOfInput); + return p; + } + if (IsValid(m_ptr)) { ch = *m_ptr; if (ch == '=') { @@ -191,6 +214,11 @@ std::unique_ptr<CXFA_FMToken> CXFA_FMLexer::Scan() { return p; case '>': ++m_ptr; + if (m_ptr > m_end) { + Error(kFMErrEndOfInput); + return p; + } + if (IsValid(m_ptr)) { ch = *m_ptr; if (ch == '=') { @@ -246,6 +274,11 @@ std::unique_ptr<CXFA_FMToken> CXFA_FMLexer::Scan() { return p; case '/': { ++m_ptr; + if (m_ptr > m_end) { + Error(kFMErrEndOfInput); + return p; + } + if (!IsValid(m_ptr)) { ch = *m_ptr; Error(kFMErrUnsupportedChar, ch); @@ -261,6 +294,11 @@ std::unique_ptr<CXFA_FMToken> CXFA_FMLexer::Scan() { } case '.': ++m_ptr; + if (m_ptr > m_end) { + Error(kFMErrEndOfInput); + return p; + } + if (IsValid(m_ptr)) { ch = *m_ptr; if (ch == '.') { @@ -316,6 +354,11 @@ const wchar_t* CXFA_FMLexer::String(CXFA_FMToken* t, const wchar_t* p) { const wchar_t* pStart = p; ++p; + if (p > m_end) { + Error(kFMErrEndOfInput); + return p; + } + uint16_t ch = *p; while (ch) { if (!IsValid(p)) { @@ -324,13 +367,18 @@ const wchar_t* CXFA_FMLexer::String(CXFA_FMToken* t, const wchar_t* p) { Error(kFMErrUnsupportedChar, ch); return p; } + + ++p; + if (p > m_end) { + Error(kFMErrEndOfInput); + return p; + } + if (ch != '"') { - ++p; ch = *p; continue; } - ++p; if (!IsValid(p)) { ch = *p; t->m_wstring = CFX_WideStringC(pStart, (p - pStart)); @@ -342,6 +390,10 @@ const wchar_t* CXFA_FMLexer::String(CXFA_FMToken* t, const wchar_t* p) { break; ++p; + if (p > m_end) { + Error(kFMErrEndOfInput); + return p; + } ch = *p; } t->m_wstring = CFX_WideStringC(pStart, (p - pStart)); @@ -352,6 +404,11 @@ const wchar_t* CXFA_FMLexer::Identifiers(CXFA_FMToken* t, const wchar_t* p) { const wchar_t* pStart = p; uint16_t ch = *p; ++p; + if (p > m_end) { + Error(kFMErrEndOfInput); + return p; + } + if (!IsValid(p)) { t->m_wstring = CFX_WideStringC(pStart, (p - pStart)); Error(kFMErrUnsupportedChar, ch); @@ -375,6 +432,10 @@ const wchar_t* CXFA_FMLexer::Identifiers(CXFA_FMToken* t, const wchar_t* p) { break; } ++p; + if (p > m_end) { + Error(kFMErrEndOfInput); + return p; + } } t->m_wstring = CFX_WideStringC(pStart, (p - pStart)); t->m_type = IsKeyword(t->m_wstring); @@ -383,18 +444,30 @@ const wchar_t* CXFA_FMLexer::Identifiers(CXFA_FMToken* t, const wchar_t* p) { const wchar_t* CXFA_FMLexer::Comment(const wchar_t* p) { ++p; + + if (p > m_end) { + Error(kFMErrEndOfInput); + return p; + } + unsigned ch = *p; while (ch) { - if (ch == 0x0D) { + if (ch == L'\r') { ++p; + if (p > m_end) + Error(kFMErrEndOfInput); return p; } - if (ch == 0x0A) { + + ++p; + if (p > m_end) { + Error(kFMErrEndOfInput); + return p; + } + if (ch == L'\n') { ++m_uCurrentLine; - ++p; return p; } - ++p; ch = *p; } return p; diff --git a/xfa/fxfa/fm2js/xfa_lexer.h b/xfa/fxfa/fm2js/xfa_lexer.h index 5dd10c2d63..0db9de58a9 100644 --- a/xfa/fxfa/fm2js/xfa_lexer.h +++ b/xfa/fxfa/fm2js/xfa_lexer.h @@ -126,6 +126,7 @@ class CXFA_FMLexer { std::unique_ptr<CXFA_FMToken> Scan(); const wchar_t* m_ptr; + const wchar_t* const m_end; uint32_t m_uCurrentLine; std::unique_ptr<CXFA_FMToken> m_pToken; CXFA_FMErrorInfo* m_pErrorInfo; |