Backport of: From aaf5327649e8f7371c9d3270e7813c43ddfd47ee Mon Sep 17 00:00:00 2001 From: Albert Astals Cid <aacid@kde.org> Date: Wed, 13 Sep 2017 23:01:03 +0200 Subject: Gfx::doShowText: Fix infinite recursion on broken files Bug #102701 Index: poppler-0.24.5/poppler/Gfx.cc =================================================================== --- poppler-0.24.5.orig/poppler/Gfx.cc +++ poppler-0.24.5/poppler/Gfx.cc @@ -3947,12 +3947,34 @@ 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; + Object charProc2; + if (charProc.isRef()) { + refNum = charProc.getRef().num; + charProc.fetch(((Gfx8BitFont *)font)->getCharProcs()->getXRef(), &charProc2); + } if ((resDict = ((Gfx8BitFont *)font)->getResources())) { pushResources(resDict); } - if (charProc.isStream()) { - display(&charProc, gFalse); + if (charProc2.isStream()) { + std::set<int>::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(&charProc2, gFalse); + + if (refNum != -1) { + charProcDrawing.erase(charProcDrawingIt); + } + } } else { error(errSyntaxError, getPos(), "Missing or bad Type3 CharProc entry"); } @@ -3960,6 +3982,7 @@ void Gfx::doShowText(GooString *s) { if (resDict) { popResources(); } + charProc2.free(); charProc.free(); } restoreStateStack(savedState); Index: poppler-0.24.5/poppler/Gfx.h =================================================================== --- poppler-0.24.5.orig/poppler/Gfx.h +++ poppler-0.24.5/poppler/Gfx.h @@ -226,6 +226,8 @@ private: Parser *parser; // parser for page content stream(s) std::set<int> formsDrawing; // the forms that are being drawn + std::set<int> charProcDrawing; // the charProc that are being drawn + GBool // callback to check for an abort (*abortCheckCbk)(void *data); Index: poppler-0.24.5/poppler/GfxFont.cc =================================================================== --- poppler-0.24.5.orig/poppler/GfxFont.cc +++ poppler-0.24.5/poppler/GfxFont.cc @@ -1744,6 +1744,15 @@ Object *Gfx8BitFont::getCharProc(int cod return proc; } +Object *Gfx8BitFont::getCharProcNF(int code, Object *proc) { + if (enc[code] && charProcs.isDict()) { + return charProcs.dictLookupNF(enc[code], proc); + } else { + proc->initNull(); + } + return proc; +} + Dict *Gfx8BitFont::getResources() { return resources.isDict() ? resources.getDict() : (Dict *)NULL; } Index: poppler-0.24.5/poppler/GfxFont.h =================================================================== --- poppler-0.24.5.orig/poppler/GfxFont.h +++ poppler-0.24.5/poppler/GfxFont.h @@ -340,6 +340,7 @@ public: // Return the Type 3 CharProc for the character associated with <code>. Object *getCharProc(int code, Object *proc); + Object *getCharProcNF(int code, Object *proc); // Return the Type 3 Resources dictionary, or NULL if none. Dict *getResources();