diff options
author | David Benjamin <davidben@mit.edu> | 2010-01-27 22:40:33 +0000 |
---|---|---|
committer | Albert Astals Cid <aacid@kde.org> | 2010-01-27 22:41:57 +0000 |
commit | 8284008aa8230a92ba08d547864353d3290e9bf9 (patch) | |
tree | 9b5a7e75bc053bbbb1884413a82479f9a3397980 | |
parent | 4ae84c830f842d100cbb702b32970951a5a5769f (diff) |
Add a stack of stateGuards to Gfx
While a stack of states is a good way to maintain graphics contexts, if
the command stream you are interpreting is untrusted, we must place
appropriate guards to be sure that, not only do we not pop past the end
of the stack, but we do not pop past the stack as it was when we began
rendering.
-rw-r--r-- | poppler/Gfx.cc | 30 | ||||
-rw-r--r-- | poppler/Gfx.h | 11 |
2 files changed, 40 insertions, 1 deletions
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc index a9429b87..a3ed7230 100644 --- a/poppler/Gfx.cc +++ b/poppler/Gfx.cc @@ -30,7 +30,7 @@ // Copyright (C) 2009 M Joonas Pihlaja <jpihlaja@cc.helsinki.fi> // Copyright (C) 2009 Thomas Freitag <Thomas.Freitag@alfa.de> // Copyright (C) 2009 William Bader <williambader@hotmail.com> -// Copyright (C) 2009 David Benjamin <davidben@mit.edu> +// Copyright (C) 2009, 2010 David Benjamin <davidben@mit.edu> // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git @@ -543,6 +543,7 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, Catalog *cata out = outA; state = new GfxState(hDPI, vDPI, box, rotate, out->upsideDown()); stackHeight = 1; + pushStateGuard(); fontChanged = gFalse; clip = clipNone; ignoreUndef = 0; @@ -596,6 +597,7 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict, Catalog *catalogA, out = outA; state = new GfxState(72, 72, box, 0, gFalse); stackHeight = 1; + pushStateGuard(); fontChanged = gFalse; clip = clipNone; ignoreUndef = 0; @@ -620,7 +622,12 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict, Catalog *catalogA, } Gfx::~Gfx() { + while (stateGuards.size()) { + popStateGuard(); + } + // There shouldn't be more saves, but pop them if there were any while (state->hasSaves()) { + error(-1, "Found state under last state guard. Popping."); restoreState(); } if (!subPage) { @@ -668,6 +675,7 @@ void Gfx::go(GBool topLevel) { int lastAbortCheck; // scan a sequence of objects + pushStateGuard(); updateLevel = lastAbortCheck = 0; numArgs = 0; parser->getObj(&obj); @@ -766,6 +774,8 @@ void Gfx::go(GBool topLevel) { args[i].free(); } + popStateGuard(); + // update display if (topLevel && updateLevel > 0) { out->dump(); @@ -4746,6 +4756,20 @@ void Gfx::drawAnnot(Object *str, AnnotBorder *border, AnnotColor *aColor, double } } +int Gfx::bottomGuard() { + return stateGuards[stateGuards.size()-1]; +} + +void Gfx::pushStateGuard() { + stateGuards.push_back(stackHeight); +} + +void Gfx::popStateGuard() { + while (stackHeight > bottomGuard() && state->hasSaves()) + restoreState(); + stateGuards.pop_back(); +} + void Gfx::saveState() { out->saveState(state); state = state->save(); @@ -4753,6 +4777,10 @@ void Gfx::saveState() { } void Gfx::restoreState() { + if (stackHeight <= bottomGuard() || !state->hasSaves()) { + error(-1, "Restoring state when no valid states to pop"); + return; + } state = state->restore(); out->restoreState(state); stackHeight--; diff --git a/poppler/Gfx.h b/poppler/Gfx.h index 2a808ce4..fb4e3644 100644 --- a/poppler/Gfx.h +++ b/poppler/Gfx.h @@ -19,6 +19,7 @@ // Copyright (C) 2008, 2010 Carlos Garcia Campos <carlosgc@gnome.org> // Copyright (C) 2009 Albert Astals Cid <aacid@kde.org> // Copyright (C) 2009 Thomas Freitag <Thomas.Freitag@alfa.de> +// Copyright (C) 2010 David Benjamin <davidben@mit.edu> // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git @@ -34,6 +35,7 @@ #include "goo/gtypes.h" #include "goo/GooList.h" +#include "goo/GooVector.h" #include "GfxState.h" #include "Object.h" #include "PopplerCache.h" @@ -163,9 +165,15 @@ public: // Save graphics state. void saveState(); + // Push a new state guard + void pushStateGuard(); + // Restore graphics state. void restoreState(); + // Pop to state guard and pop guard + void popStateGuard(); + // Get the current graphics state object. GfxState *getState() { return state; } @@ -194,6 +202,7 @@ private: GfxState *state; // current graphics state int stackHeight; // the height of the current graphics stack + GooVector<int> stateGuards; // a stack of state limits; to guard against unmatched pops GBool fontChanged; // set if font or text matrix has changed GfxClipType clip; // do a clip? int ignoreUndef; // current BX/EX nesting level @@ -221,6 +230,8 @@ private: GBool checkArg(Object *arg, TchkType type); int getPos(); + int bottomGuard(); + // graphics state operators void opSave(Object args[], int numArgs); void opRestore(Object args[], int numArgs); |