diff --git a/xpdf/xpdf/CharCodeToUnicode.cc b/xpdf/xpdf/CharCodeToUnicode.cc index ae6e1e4c8..650424891 100644 --- a/xpdf/xpdf/CharCodeToUnicode.cc +++ b/xpdf/xpdf/CharCodeToUnicode.cc @@ -243,8 +243,18 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, } if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' && tok2[0] == '<' && tok2[n2 - 1] == '>')) { - error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); - continue; + + // check there was no line jump inside the token and so the length is + // longer than it should be + int countAux = 0; + for (int k = 0; k < n1; k++) + if (tok1[k] != '\n' && tok1[k] != '\r') countAux++; + + if (!(countAux == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' && + tok2[0] == '<' && tok2[n2 - 1] == '>')) { + error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); + continue; + } } tok1[n1 - 1] = tok2[n2 - 1] = '\0'; if (sscanf(tok1 + 1, "%x", &code1) != 1) { @@ -268,8 +278,21 @@ void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, } if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' && n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) { - error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); - continue; + // check there was no line jump inside the token and so the length is + // longer than it should be + int countAux = 0; + for (int k = 0; k < n1; k++) + if (tok1[k] != '\n' && tok1[k] != '\r') countAux++; + + int countAux2 = 0; + for (int k = 0; k < n1; k++) + if (tok2[k] != '\n' && tok2[k] != '\r') countAux++; + + if (!(countAux == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' && + countAux2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) { + error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); + continue; + } } tok1[n1 - 1] = tok2[n2 - 1] = '\0'; if (sscanf(tok1 + 1, "%x", &code1) != 1 || diff --git a/xpdf/xpdf/Lexer.cc b/xpdf/xpdf/Lexer.cc index 7cef92178..5cbcc33a3 100644 --- a/xpdf/xpdf/Lexer.cc +++ b/xpdf/xpdf/Lexer.cc @@ -18,6 +18,7 @@ #include #include "Lexer.h" #include "Error.h" +#include "XRef.h" //------------------------------------------------------------------------ @@ -46,9 +47,11 @@ static char Lexer_specialChars[256] = { // Lexer //------------------------------------------------------------------------ -Lexer::Lexer(XRef *xref, Stream *str) { +Lexer::Lexer(XRef *xrefA, Stream *str) { Object obj; + xref = xrefA; + curStr.initStream(str); streams = new Array(xref); streams->add(curStr.copy(&obj)); @@ -57,9 +60,11 @@ Lexer::Lexer(XRef *xref, Stream *str) { curStr.streamReset(); } -Lexer::Lexer(XRef *xref, Object *obj) { +Lexer::Lexer(XRef *xrefA, Object *obj) { Object obj2; + xref = xrefA; + if (obj->isStream()) { streams = new Array(xref); freeArray = gTrue; @@ -108,7 +113,7 @@ int Lexer::lookChar() { return curStr.streamLookChar(); } -Object *Lexer::getObj(Object *obj) { +Object *Lexer::getObj(Object *obj, int objNum) { char *p; int c, c2; GBool comment, neg, done; @@ -291,6 +296,17 @@ Object *Lexer::getObj(Object *obj) { s->append(tokBuf, tokBufSize); p = tokBuf; n = 0; + + // we are growing see if the document is not malformed and we are growing too much + if (objNum != -1) + { + int newObjNum = xref->getNumEntry(getPos()); + if (newObjNum != objNum) + { + error(getPos(), "Unterminated string"); + done = gTrue; + } + } } *p++ = (char)c2; ++n; diff --git a/xpdf/xpdf/Lexer.h b/xpdf/xpdf/Lexer.h index f6ad9ce96..3333be9f9 100644 --- a/xpdf/xpdf/Lexer.h +++ b/xpdf/xpdf/Lexer.h @@ -31,17 +31,17 @@ public: // Construct a lexer for a single stream. Deletes the stream when // lexer is deleted. - Lexer(XRef *xref, Stream *str); + Lexer(XRef *xrefA, Stream *str); // Construct a lexer for a stream or array of streams (assumes obj // is either a stream or array of streams). - Lexer(XRef *xref, Object *obj); + Lexer(XRef *xrefA, Object *obj); // Destructor. ~Lexer(); // Get the next object from the input stream. - Object *getObj(Object *obj); + Object *getObj(Object *obj, int objNum = -1); // Skip to the beginning of the next line in the input stream. void skipToNextLine(); @@ -75,6 +75,8 @@ private: Object curStr; // current stream GBool freeArray; // should lexer free the streams array? char tokBuf[tokBufSize]; // temporary token buffer + + XRef *xref; }; #endif diff --git a/xpdf/xpdf/Parser.cc b/xpdf/xpdf/Parser.cc index e9e3809ed..d6732fcd6 100644 --- a/xpdf/xpdf/Parser.cc +++ b/xpdf/xpdf/Parser.cc @@ -69,7 +69,7 @@ Object *Parser::getObj(Object *obj, // dictionary or stream } else if (buf1.isCmd("<<")) { - shift(); + shift(objNum); obj->initDict(xref); while (!buf1.isCmd(">>") && !buf1.isEOF()) { if (!buf1.isName()) { @@ -195,7 +195,7 @@ Stream *Parser::makeStream(Object *dict) { return str; } -void Parser::shift() { +void Parser::shift(int objNum) { if (inlineImg > 0) { if (inlineImg < 2) { ++inlineImg; @@ -213,5 +213,5 @@ void Parser::shift() { if (inlineImg > 0) // don't buffer inline image data buf2.initNull(); else - lexer->getObj(&buf2); + lexer->getObj(&buf2, objNum); } diff --git a/xpdf/xpdf/Parser.h b/xpdf/xpdf/Parser.h index b583baf63..fd23a0a35 100644 --- a/xpdf/xpdf/Parser.h +++ b/xpdf/xpdf/Parser.h @@ -49,7 +49,7 @@ private: int inlineImg; // set when inline image data is encountered Stream *makeStream(Object *dict); - void shift(); + void shift(int objNum = -1); }; #endif diff --git a/xpdf/xpdf/XRef.cc b/xpdf/xpdf/XRef.cc index accbff3cc..aac0e29c9 100644 --- a/xpdf/xpdf/XRef.cc +++ b/xpdf/xpdf/XRef.cc @@ -876,6 +876,23 @@ GBool XRef::getStreamEnd(Guint streamStart, Guint *streamEnd) { return gTrue; } +int XRef::getNumEntry(int offset) const +{ + int res = -1; + int resOffset = -1; + XRefEntry e; + for (int i = 0; i < size; ++i) + { + e = entries[i]; + if (e.offset < offset && e.offset > resOffset) + { + res = i; + resOffset = e.offset; + } + } + return res; +} + Guint XRef::strToUnsigned(char *s) { Guint x; char *p; diff --git a/xpdf/xpdf/XRef.h b/xpdf/xpdf/XRef.h index f9dede3e7..633141aa0 100644 --- a/xpdf/xpdf/XRef.h +++ b/xpdf/xpdf/XRef.h @@ -91,6 +91,9 @@ public: // Returns false if unknown or file is not damaged. GBool getStreamEnd(Guint streamStart, Guint *streamEnd); + // Retuns the entry that belongs to the offset + int getNumEntry(int offset) const; + // Direct access. int getSize() { return size; } XRefEntry *getEntry(int i) { return &entries[i]; }