From 778180c0c09002f6adfc272eba6b0d0e4401c4cc Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Wed, 13 Sep 2017 23:01:03 +0200 Subject: [PATCH 3/4] Gfx::doShowText: Fix infinite recursion on broken files Bug #102701 --- poppler/Gfx.cc | 25 +++++++++++++++++++++++-- poppler/Gfx.h | 1 + poppler/GfxFont.cc | 9 +++++++++ poppler/GfxFont.h | 1 + 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc index 37220280..9feac54c 100644 --- a/poppler/Gfx.cc +++ b/poppler/Gfx.cc @@ -4031,12 +4031,33 @@ void Gfx::doShowText(GooString *s) { state->transformDelta(dx, dy, &ddx, &ddy); if (!out->beginType3Char(state, curX + riseX, curY + riseY, ddx, ddy, code, u, uLen)) { - ((Gfx8BitFont *)font)->getCharProc(code, &charProc); + ((Gfx8BitFont *)font)->getCharProcNF(code, &charProc); + int refNum = -1; + if (charProc.isRef()) { + refNum = charProc.getRef().num; + charProc.fetch(((Gfx8BitFont *)font)->getCharProcs()->getXRef(), &charProc); + } if ((resDict = ((Gfx8BitFont *)font)->getResources())) { pushResources(resDict); } if (charProc.isStream()) { - display(&charProc, gFalse); + std::set::iterator charProcDrawingIt; + bool displayCharProc = true; + if (refNum != -1) { + if (charProcDrawing.find(refNum) == charProcDrawing.end()) { + charProcDrawingIt = charProcDrawing.insert(refNum).first; + } else { + displayCharProc = false; + error(errSyntaxError, -1, "CharProc wants to draw a CharProc that is already beign drawn"); + } + } + if (displayCharProc) { + display(&charProc, gFalse); + + if (refNum != -1) { + charProcDrawing.erase(charProcDrawingIt); + } + } } else { error(errSyntaxError, getPos(), "Missing or bad Type3 CharProc entry"); } diff --git a/poppler/Gfx.h b/poppler/Gfx.h index a82f9f4a..44adaed5 100644 --- a/poppler/Gfx.h +++ b/poppler/Gfx.h @@ -228,6 +228,7 @@ private: Parser *parser; // parser for page content stream(s) std::set formsDrawing; // the forms that are being drawn + std::set charProcDrawing; // the charProc that are being drawn GBool // callback to check for an abort (*abortCheckCbk)(void *data); diff --git a/poppler/GfxFont.cc b/poppler/GfxFont.cc index b59ec06c..bb87c5a0 100644 --- a/poppler/GfxFont.cc +++ b/poppler/GfxFont.cc @@ -1818,6 +1818,15 @@ Object *Gfx8BitFont::getCharProc(int code, Object *proc) { return proc; } +Object *Gfx8BitFont::getCharProcNF(int code, Object *proc) { + if (enc[code] && charProcs.isDict()) { + charProcs.dictLookupNF(enc[code], proc); + } else { + proc->initNull(); + } + return proc; +} + Dict *Gfx8BitFont::getResources() { return resources.isDict() ? resources.getDict() : (Dict *)NULL; } diff --git a/poppler/GfxFont.h b/poppler/GfxFont.h index de7a7464..89a0ca0d 100644 --- a/poppler/GfxFont.h +++ b/poppler/GfxFont.h @@ -353,6 +353,7 @@ public: // Return the Type 3 CharProc for the character associated with . Object *getCharProc(int code, Object *proc); + Object *getCharProcNF(int code, Object *proc); // Return the Type 3 Resources dictionary, or NULL if none. Dict *getResources(); -- 2.14.1