Skip to content

Commit 579d703

Browse files
authored
feat: resolving invalid parsing causing stack overflow (#280)
1 parent ad6258c commit 579d703

File tree

5 files changed

+48
-3
lines changed

5 files changed

+48
-3
lines changed

.vscode/settings.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"unordered_map": "cpp",
6969
"variant": "cpp",
7070
"algorithm": "cpp",
71-
"tiffio.h": "c"
71+
"tiffio.h": "c",
72+
"utility": "cpp"
7273
}
7374
}

PDFWriter/PDFObjectParser.cpp

+43-2
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,16 @@
4545

4646
using namespace PDFHummus;
4747

48+
#define MAX_OBJECT_DEPTH 100 // While PDF does not explicitly define arrays and dicts depth...we do, due to call stack depth limit...and to avoid potential malarky.
49+
4850

4951
PDFObjectParser::PDFObjectParser(void)
5052
{
5153
mParserExtender = NULL;
5254
mDecryptionHelper = NULL;
5355
mOwnsStream = false;
5456
mStream = NULL;
57+
mDepth = 0;
5558
}
5659

5760
PDFObjectParser::~PDFObjectParser(void)
@@ -79,6 +82,7 @@ void PDFObjectParser::ResetReadState()
7982
{
8083
mTokenBuffer.clear();
8184
mTokenizer.ResetReadState();
85+
mDepth = 0;
8286
}
8387

8488
void PDFObjectParser::ResetReadState(const PDFParserTokenizer& inExternalTokenizer)
@@ -584,14 +588,40 @@ bool PDFObjectParser::IsArray(const std::string& inToken)
584588
return scLeftSquare == inToken;
585589
}
586590

591+
EStatusCode PDFObjectParser::IncreaseAndCheckDepth() {
592+
++mDepth;
593+
if(mDepth > MAX_OBJECT_DEPTH) {
594+
TRACE_LOG1("PDFObjectParser::IncreaseAndCeckDepth, reached maximum allowed depth of %d", MAX_OBJECT_DEPTH);
595+
return eFailure;
596+
}
597+
598+
return eSuccess;
599+
}
600+
601+
EStatusCode PDFObjectParser::DecreaseAndCheckDepth() {
602+
--mDepth;
603+
if(mDepth < 0) {
604+
TRACE_LOG("PDFObjectParser::DecreaseAndCheckDepth, anomaly. managed to get to negative depth");
605+
return eFailure;
606+
}
607+
608+
return eSuccess;
609+
}
610+
611+
587612
static const std::string scRightSquare = "]";
588613
PDFObject* PDFObjectParser::ParseArray()
589614
{
590-
PDFArray* anArray = new PDFArray();
615+
PDFArray* anArray;
591616
bool arrayEndEncountered = false;
592617
std::string token;
593618
EStatusCode status = PDFHummus::eSuccess;
594619

620+
if(IncreaseAndCheckDepth() != eSuccess)
621+
return NULL;
622+
623+
anArray = new PDFArray();
624+
595625
// easy one. just loop till you get to a closing bracket token and recurse
596626
while(GetNextToken(token) && PDFHummus::eSuccess == status)
597627
{
@@ -612,6 +642,9 @@ PDFObject* PDFObjectParser::ParseArray()
612642
}
613643
}
614644

645+
if(DecreaseAndCheckDepth() != eSuccess)
646+
status = eFailure;
647+
615648
if(arrayEndEncountered && PDFHummus::eSuccess == status)
616649
{
617650
return anArray;
@@ -643,11 +676,16 @@ bool PDFObjectParser::IsDictionary(const std::string& inToken)
643676
static const std::string scDoubleRightAngle = ">>";
644677
PDFObject* PDFObjectParser::ParseDictionary()
645678
{
646-
PDFDictionary* aDictionary = new PDFDictionary();
679+
PDFDictionary* aDictionary;
647680
bool dictionaryEndEncountered = false;
648681
std::string token;
649682
EStatusCode status = PDFHummus::eSuccess;
650683

684+
if(IncreaseAndCheckDepth() != eSuccess)
685+
return NULL;
686+
687+
aDictionary = new PDFDictionary();
688+
651689
while(GetNextToken(token) && PDFHummus::eSuccess == status)
652690
{
653691
dictionaryEndEncountered = (scDoubleRightAngle == token);
@@ -681,6 +719,9 @@ PDFObject* PDFObjectParser::ParseDictionary()
681719
aDictionary->Insert(aKey.GetPtr(),aValue.GetPtr());
682720
}
683721

722+
if(DecreaseAndCheckDepth() != eSuccess)
723+
status = eFailure;
724+
684725
if(dictionaryEndEncountered && PDFHummus::eSuccess == status)
685726
{
686727
return aDictionary;

PDFWriter/PDFObjectParser.h

+3
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ class PDFObjectParser
7878
IPDFParserExtender* mParserExtender;
7979
DecryptionHelper* mDecryptionHelper;
8080
bool mOwnsStream;
81+
int mDepth;
8182

8283
bool GetNextToken(std::string& outToken);
8384
void SaveTokenToBuffer(std::string& inToken);
@@ -112,5 +113,7 @@ class PDFObjectParser
112113

113114
std::string MaybeDecryptString(const std::string& inString);
114115

116+
PDFHummus::EStatusCode IncreaseAndCheckDepth();
117+
PDFHummus::EStatusCode DecreaseAndCheckDepth();
115118

116119
};
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)