summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Sinclair <dsinclair@chromium.org>2017-05-16 11:45:23 -0400
committerChromium commit bot <commit-bot@chromium.org>2017-05-16 16:00:10 +0000
commit2eef64cba5c8e08a9e625f4aba5a7fbdc8e62bad (patch)
tree38a70cf1d91fc56a64a4525c041447c203b07f49
parent2a835b7b902bc0b61b1a3618f5c82b91571ecd72 (diff)
downloadpdfium-2eef64cba5c8e08a9e625f4aba5a7fbdc8e62bad.tar.xz
Do not walk off end of formcalc string
The fm2js code takes a pointer to the input string and then walks along that pointer. There are currently no checks to verify we haven't walked off the end of the pointer into random memory. If this happens, we can end up allocating large chunks of memory and copying random bits. BUG=chromium:721533 Change-Id: Ia61fe96c1ff9eb9ded63cf8326b7be44986bd9e1 Reviewed-on: https://pdfium-review.googlesource.com/5550 Commit-Queue: dsinclair <dsinclair@chromium.org> Reviewed-by: Nicolás Peña <npm@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org>
-rw-r--r--xfa/fxfa/fm2js/xfa_error.cpp1
-rw-r--r--xfa/fxfa/fm2js/xfa_error.h1
-rw-r--r--xfa/fxfa/fm2js/xfa_lexer.cpp89
-rw-r--r--xfa/fxfa/fm2js/xfa_lexer.h1
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;