summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthestig <thestig@chromium.org>2016-04-28 14:45:28 -0700
committerCommit bot <commit-bot@chromium.org>2016-04-28 14:45:28 -0700
commit8e957baa851aed4b02511d04a66c0f95387d1e10 (patch)
treecf601eda1637d84cb7c5f01d30ea18b52c965dca
parent01a86203141df4a61ae90e289f62c4daf31ee2ba (diff)
downloadpdfium-8e957baa851aed4b02511d04a66c0f95387d1e10.tar.xz
Fix stack overflow from nested arrays.
BUG=pdfium:422 Review-Url: https://codereview.chromium.org/1930743003
-rw-r--r--core/fpdfapi/fpdf_page/fpdf_page_parser.cpp2
-rw-r--r--core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp101
-rw-r--r--core/fpdfapi/fpdf_page/pageint.h4
3 files changed, 56 insertions, 51 deletions
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp b/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
index 93ea93dee7..7ed485c87c 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
@@ -604,7 +604,7 @@ void CPDF_StreamContentParser::Handle_BeginImage() {
CFX_ByteString key((const FX_CHAR*)m_pSyntax->GetWordBuf() + 1,
m_pSyntax->GetWordSize() - 1);
std::unique_ptr<CPDF_Object, ReleaseDeleter<CPDF_Object>> pObj(
- m_pSyntax->ReadNextObject());
+ m_pSyntax->ReadNextObject(false, 0));
if (!key.IsEmpty()) {
uint32_t dwObjNum = pObj ? pObj->GetObjNum() : 0;
if (dwObjNum)
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp b/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
index 47c0336ea9..58ecb6c4d6 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
@@ -31,6 +31,14 @@
#include "core/fxcrt/include/fx_ext.h"
#include "core/fxcrt/include/fx_safe_types.h"
+namespace {
+
+const uint32_t kMaxNestedArrayLevel = 512;
+const uint32_t kMaxWordBuffer = 256;
+const FX_STRSIZE kMaxStringLength = 32767;
+
+} // namespace
+
CPDF_StreamParser::CPDF_StreamParser(const uint8_t* pData, uint32_t dwSize) {
m_pBuf = pData;
m_Size = dwSize;
@@ -230,9 +238,6 @@ CPDF_Stream* CPDF_StreamParser::ReadInlineStream(CPDF_Document* pDoc,
return new CPDF_Stream(pData, dwStreamSize, pDict);
}
-#define MAX_WORD_BUFFER 256
-#define MAX_STRING_LENGTH 32767
-
CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement() {
if (m_pLastObj) {
m_pLastObj->Release();
@@ -268,12 +273,12 @@ CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement() {
if (PDFCharIsDelimiter(ch) && ch != '/') {
m_Pos--;
- m_pLastObj = ReadNextObject();
+ m_pLastObj = ReadNextObject(false, 0);
return Others;
}
while (1) {
- if (m_WordSize < MAX_WORD_BUFFER)
+ if (m_WordSize < kMaxWordBuffer)
m_WordBuffer[m_WordSize++] = ch;
if (!PDFCharIsNumeric(ch))
@@ -315,88 +320,90 @@ CPDF_StreamParser::SyntaxType CPDF_StreamParser::ParseNextElement() {
return Keyword;
}
-CPDF_Object* CPDF_StreamParser::ReadNextObject(FX_BOOL bAllowNestedArray,
- FX_BOOL bInArray) {
+CPDF_Object* CPDF_StreamParser::ReadNextObject(bool bAllowNestedArray,
+ uint32_t dwInArrayLevel) {
FX_BOOL bIsNumber;
GetNextWord(bIsNumber);
- if (m_WordSize == 0) {
- return NULL;
- }
+ if (!m_WordSize)
+ return nullptr;
+
if (bIsNumber) {
m_WordBuffer[m_WordSize] = 0;
return new CPDF_Number(CFX_ByteStringC(m_WordBuffer, m_WordSize));
}
+
int first_char = m_WordBuffer[0];
if (first_char == '/') {
return new CPDF_Name(
PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1)));
}
- if (first_char == '(') {
+
+ if (first_char == '(')
return new CPDF_String(ReadString(), FALSE);
- }
+
if (first_char == '<') {
- if (m_WordSize == 1) {
+ if (m_WordSize == 1)
return new CPDF_String(ReadHexString(), TRUE);
- }
+
CPDF_Dictionary* pDict = new CPDF_Dictionary;
while (1) {
GetNextWord(bIsNumber);
- if (m_WordSize == 0) {
- pDict->Release();
- return nullptr;
- }
- if (m_WordSize == 2 && m_WordBuffer[0] == '>') {
+ if (m_WordSize == 2 && m_WordBuffer[0] == '>')
break;
- }
- if (m_WordBuffer[0] != '/') {
+
+ if (!m_WordSize || m_WordBuffer[0] != '/') {
pDict->Release();
return nullptr;
}
+
CFX_ByteString key =
PDF_NameDecode(CFX_ByteStringC(m_WordBuffer + 1, m_WordSize - 1));
- CPDF_Object* pObj = ReadNextObject(TRUE);
+ CPDF_Object* pObj = ReadNextObject(true, 0);
if (!pObj) {
pDict->Release();
return nullptr;
}
- if (!key.IsEmpty()) {
- pDict->SetAt(key, pObj);
- } else {
+
+ if (key.IsEmpty())
pObj->Release();
- }
+ else
+ pDict->SetAt(key, pObj);
}
return pDict;
}
+
if (first_char == '[') {
- if (!bAllowNestedArray && bInArray) {
- return NULL;
+ if ((!bAllowNestedArray && dwInArrayLevel) ||
+ dwInArrayLevel > kMaxNestedArrayLevel) {
+ return nullptr;
}
+
CPDF_Array* pArray = new CPDF_Array;
while (1) {
- CPDF_Object* pObj = ReadNextObject(bAllowNestedArray, TRUE);
+ CPDF_Object* pObj = ReadNextObject(bAllowNestedArray, dwInArrayLevel + 1);
if (pObj) {
pArray->Add(pObj);
continue;
}
- if (m_WordSize == 0 || m_WordBuffer[0] == ']')
+ if (!m_WordSize || m_WordBuffer[0] == ']')
break;
}
return pArray;
}
+
+ if (m_WordSize == 5 && !memcmp(m_WordBuffer, "false", 5))
+ return new CPDF_Boolean(FALSE);
+
if (m_WordSize == 4) {
- if (memcmp(m_WordBuffer, "true", 4) == 0) {
+ if (memcmp(m_WordBuffer, "true", 4) == 0)
return new CPDF_Boolean(TRUE);
- }
- if (memcmp(m_WordBuffer, "null", 4) == 0) {
+
+ if (memcmp(m_WordBuffer, "null", 4) == 0)
return new CPDF_Null;
- }
- } else if (m_WordSize == 5) {
- if (memcmp(m_WordBuffer, "false", 5) == 0) {
- return new CPDF_Boolean(FALSE);
- }
}
- return NULL;
+
+ return nullptr;
}
void CPDF_StreamParser::GetNextWord(FX_BOOL& bIsNumber) {
@@ -439,7 +446,7 @@ void CPDF_StreamParser::GetNextWord(FX_BOOL& bIsNumber) {
return;
}
- if (m_WordSize < MAX_WORD_BUFFER)
+ if (m_WordSize < kMaxWordBuffer)
m_WordBuffer[m_WordSize++] = ch;
}
} else if (ch == '<') {
@@ -463,7 +470,7 @@ void CPDF_StreamParser::GetNextWord(FX_BOOL& bIsNumber) {
}
while (1) {
- if (m_WordSize < MAX_WORD_BUFFER)
+ if (m_WordSize < kMaxWordBuffer)
m_WordBuffer[m_WordSize++] = ch;
if (!PDFCharIsNumeric(ch))
bIsNumber = FALSE;
@@ -492,8 +499,8 @@ CFX_ByteString CPDF_StreamParser::ReadString() {
case 0:
if (ch == ')') {
if (parlevel == 0) {
- if (buf.GetLength() > MAX_STRING_LENGTH) {
- return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);
+ if (buf.GetLength() > kMaxStringLength) {
+ return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
}
return buf.AsStringC();
}
@@ -571,8 +578,8 @@ CFX_ByteString CPDF_StreamParser::ReadString() {
if (PositionIsInBounds())
++m_Pos;
- if (buf.GetLength() > MAX_STRING_LENGTH) {
- return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);
+ if (buf.GetLength() > kMaxStringLength) {
+ return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
}
return buf.AsStringC();
}
@@ -605,8 +612,8 @@ CFX_ByteString CPDF_StreamParser::ReadHexString() {
if (!bFirst)
buf.AppendChar((char)code);
- if (buf.GetLength() > MAX_STRING_LENGTH)
- return CFX_ByteString(buf.GetBuffer(), MAX_STRING_LENGTH);
+ if (buf.GetLength() > kMaxStringLength)
+ return CFX_ByteString(buf.GetBuffer(), kMaxStringLength);
return buf.AsStringC();
}
diff --git a/core/fpdfapi/fpdf_page/pageint.h b/core/fpdfapi/fpdf_page/pageint.h
index 2dcf2e246f..01a28e3b96 100644
--- a/core/fpdfapi/fpdf_page/pageint.h
+++ b/core/fpdfapi/fpdf_page/pageint.h
@@ -53,8 +53,7 @@ class CPDF_StreamParser {
}
uint32_t GetPos() const { return m_Pos; }
void SetPos(uint32_t pos) { m_Pos = pos; }
- CPDF_Object* ReadNextObject(FX_BOOL bAllowNestedArray = FALSE,
- FX_BOOL bInArray = FALSE);
+ CPDF_Object* ReadNextObject(bool bAllowNestedArray, uint32_t dwInArrayLevel);
protected:
friend class fpdf_page_parser_old_ReadHexString_Test;
@@ -99,7 +98,6 @@ struct ContentParam {
};
#define _FPDF_MAX_FORM_LEVEL_ 30
#define _FPDF_MAX_TYPE3_FORM_LEVEL_ 4
-#define _FPDF_MAX_OBJECT_STACK_SIZE_ 512
class CPDF_StreamContentParser {
public:
CPDF_StreamContentParser(CPDF_Document* pDoc,