In many instances, the sensible response (and what acroread does) in
case of an error is abort the PDF stream. To avoid changing the return
value of every function and using C++ exceptions, we communicate via a
commandAborted variable.

This patch, matching acroread's behavior aborts the current stream when
there are too few arguments or we pop too many times. Implementation
note 39 in Appendix H of the PDF reference contradicts the former, but
hand-crafted test PDFs as well as the file in #24575 suggest otherwise.

Unlike all the other attempts, this patch *actually* fixes the PDF in
bug #24575.
---
 poppler/Gfx.cc |   11 +++++++++++
 poppler/Gfx.h  |    1 +
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 5aba7e9..372443d 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -663,6 +663,7 @@ void Gfx::go(GBool topLevel) {
   numArgs = 0;
   parser->getObj(&obj);
   while (!obj.isEOF()) {
+    commandAborted = gFalse;
 
     // got a command - execute it
     if (obj.isCmd()) {
@@ -710,6 +711,14 @@ void Gfx::go(GBool topLevel) {
        updateLevel = 0;
       }
 
+      // did the command throw an exception
+      if (commandAborted) {
+       // don't propogate; recursive drawing comes from Form XObjects which
+       // should probably be drawn in a separate context anyway for caching
+       commandAborted = gFalse;
+       break;
+      }
+
       // check for an abort
       if (abortCheckCbk) {
        if (updateLevel - lastAbortCheck > 10) {
@@ -784,6 +793,7 @@ void Gfx::execOp(Object *cmd, Object args[], int numArgs) {
   if (op->numArgs >= 0) {
     if (numArgs < op->numArgs) {
       error(getPos(), "Too few (%d) args to '%s' operator", numArgs, name);
+      commandAborted = gTrue;
       return;
     }
     if (numArgs > op->numArgs) {
@@ -4762,6 +4772,7 @@ void Gfx::saveState() {
 void Gfx::restoreState() {
   if (stackHeight <= bottomGuard() || !state->hasSaves()) {
     error(-1, "Restoring state when no valid states to pop");
+    commandAborted = gTrue;
     return;
   }
   state = state->restore();
diff --git a/poppler/Gfx.h b/poppler/Gfx.h
index 1417d19..5999ec9 100644
--- a/poppler/Gfx.h
+++ b/poppler/Gfx.h
@@ -192,6 +192,7 @@ private:
   GBool textHaveCSPattern;     // in text drawing and text has pattern 
colorspace
   GBool drawText;              // in text drawing
   GBool maskHaveCSPattern;     // in mask drawing and mask has pattern 
colorspace
+  GBool commandAborted;         // did the previous command abort the drawing?
   GfxColorSpace *colorSpaceText;// colorspace after text has filled with 
pattern
   GfxColor colorText;          // fill color after after text has filled with 
pattern
   GfxResources *res;           // resource stack
-- 
1.6.6.137.g8333d.dirty

_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to