[poppler] Branch 'better_object' - 16 commits - CMakeLists.txt config.h.cmake configure.ac cpp/Doxyfile cpp/poppler-document.cpp cpp/tests Makefile.am NEWS poppler/Annot.cc poppler/Form.cc poppler/GfxState.cc poppler/Object.h poppler/Parser.cc poppler/SplashOutputDev.cc poppler/Stream.cc qt4/src qt5/src utils/HtmlFonts.cc utils/HtmlFonts.h utils/pdfunite.cc

Albert Astals Cid aacid at kemper.freedesktop.org
Sat Jun 17 16:35:22 UTC 2017


 CMakeLists.txt             |   61 ++++++++++++++++++++++++++++++++------
 Makefile.am                |    1 
 NEWS                       |   16 ++++++++++
 config.h.cmake             |    6 +++
 configure.ac               |   71 ++++++++++++++++++++++++++++++++++++---------
 cpp/Doxyfile               |    2 -
 cpp/poppler-document.cpp   |   13 +++++++-
 cpp/tests/poppler-dump.cpp |   18 ++++++++---
 poppler/Annot.cc           |    2 -
 poppler/Form.cc            |    6 ---
 poppler/GfxState.cc        |   18 +++++++----
 poppler/Object.h           |    7 ++++
 poppler/Parser.cc          |   11 +++++-
 poppler/SplashOutputDev.cc |    3 +
 poppler/Stream.cc          |   10 ++++++
 qt4/src/Doxyfile           |    2 -
 qt5/src/Doxyfile           |    2 -
 utils/HtmlFonts.cc         |    1 
 utils/HtmlFonts.h          |    3 -
 utils/pdfunite.cc          |   10 ++++--
 20 files changed, 210 insertions(+), 53 deletions(-)

New commits:
commit 9cecd78ff12a145fd7a61d226d54fd8f9ce19638
Merge: b5ca57db 23a2f6a2
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sat Jun 17 18:35:14 2017 +0200

    Merge remote-tracking branch 'origin/master' into better_object

diff --cc poppler/Annot.cc
index 7e1941c3,974b098b..bda5a905
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@@ -5168,16 -5393,15 +5168,16 @@@ void AnnotScreen::initialize(PDFDoc *do
    Object obj1;
  
    title = NULL;
 -  if (dict->lookup("T", &obj1)->isString()) {
 +  obj1 = dict->lookup("T");
 +  if (obj1.isString()) {
      title = obj1.getString()->copy();
    }
 -  obj1.free();
  
    action = NULL;
 -  if (dict->lookup("A", &obj1)->isDict()) {
 +  obj1 = dict->lookup("A");
 +  if (obj1.isDict()) {
      action = LinkAction::parseAction(&obj1, doc->getCatalog()->getBaseURI());
-     if (action->getKind() == actionRendition && page == 0) {
+     if (action && action->getKind() == actionRendition && page == 0) {
        error (errSyntaxError, -1, "Invalid Rendition action: associated screen annotation without P");
        delete action;
        action = NULL;
diff --cc poppler/GfxState.cc
index a9e9bb4e,b17925f4..2561d412
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@@ -5121,30 -5306,42 +5121,36 @@@ GfxPatchMeshShading *GfxPatchMeshShadin
      flagBits = obj1.getInt();
    } else {
      error(errSyntaxWarning, -1, "Missing or invalid BitsPerFlag in shading dictionary");
 -    goto err2;
 +    return nullptr;
    }
 -  obj1.free();
 -  if (dict->lookup("Decode", &obj1)->isArray() &&
 -      obj1.arrayGetLength() >= 6) {
 +  obj1 = dict->lookup("Decode");
 +  if (obj1.isArray() && obj1.arrayGetLength() >= 6) {
+     bool decodeOk = true;
 -    xMin = obj1.arrayGet(0, &obj2)->getNum(&decodeOk);
 -    obj2.free();
 -    xMax = obj1.arrayGet(1, &obj2)->getNum(&decodeOk);
 -    obj2.free();
 +    Object obj2;
-     xMin = (obj2 = obj1.arrayGet(0), obj2.getNum());
-     xMax = (obj2 = obj1.arrayGet(1), obj2.getNum());
++    xMin = (obj2 = obj1.arrayGet(0), obj2.getNum(&decodeOk));
++    xMax = (obj2 = obj1.arrayGet(1), obj2.getNum(&decodeOk));
      xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1);
-     yMin = (obj2 = obj1.arrayGet(2), obj2.getNum());
-     yMax = (obj2 = obj1.arrayGet(3), obj2.getNum());
 -    yMin = obj1.arrayGet(2, &obj2)->getNum(&decodeOk);
 -    obj2.free();
 -    yMax = obj1.arrayGet(3, &obj2)->getNum(&decodeOk);
 -    obj2.free();
++    yMin = (obj2 = obj1.arrayGet(2), obj2.getNum(&decodeOk));
++    yMax = (obj2 = obj1.arrayGet(3), obj2.getNum(&decodeOk));
      yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1);
      for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) {
-       cMin[i] = (obj2 = obj1.arrayGet(4 + 2*i), obj2.getNum());
-       cMax[i] = (obj2 = obj1.arrayGet(5 + 2*i), obj2.getNum());
 -      cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum(&decodeOk);
 -      obj2.free();
 -      cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum(&decodeOk);
 -      obj2.free();
++      cMin[i] = (obj2 = obj1.arrayGet(4 + 2*i), obj2.getNum(&decodeOk));
++      cMax[i] = (obj2 = obj1.arrayGet(5 + 2*i), obj2.getNum(&decodeOk));
        cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1);
      }
      nComps = i;
+ 
+     if (!decodeOk) {
+       error(errSyntaxWarning, -1, "Missing or invalid Decode array in shading dictionary");
 -      goto err2;
++      return nullptr;
+     }
    } else {
      error(errSyntaxWarning, -1, "Missing or invalid Decode array in shading dictionary");
 -    goto err2;
 +    return nullptr;
    }
 -  obj1.free();
  
 -  if (!dict->lookup("Function", &obj1)->isNull()) {
 +  obj1 = dict->lookup("Function");
 +  if (!obj1.isNull()) {
      if (obj1.isArray()) {
        nFuncsA = obj1.arrayGetLength();
        if (nFuncsA > gfxColorMaxComps) {
diff --cc poppler/Parser.cc
index 6e71354a,8079ca1d..07e220f4
--- a/poppler/Parser.cc
+++ b/poppler/Parser.cc
@@@ -82,14 -87,19 +82,18 @@@ Object Parser::getObj(GBool simpleOnly
      inlineImg = 0;
    }
  
+   if (unlikely(recursion >= recursionLimit)) {
 -    obj->free();
 -    obj->initError();
 -    return obj;
++    return Object(objError);
+   }
+ 
    // array
-   if (!simpleOnly && likely(recursion < recursionLimit) && buf1.isCmd("[")) {
+   if (!simpleOnly && buf1.isCmd("[")) {
      shift();
 -    obj->initArray(xref);
 -    while (!buf1.isCmd("]") && !buf1.isEOF())
 -      obj->arrayAdd(getObj(&obj2, gFalse, fileKey, encAlgorithm, keyLength,
 -			   objNum, objGen, recursion + 1));
 +    obj = Object(new Array(xref));
 +    while (!buf1.isCmd("]") && !buf1.isEOF()) {
 +      Object obj2 = getObj(gFalse, fileKey, encAlgorithm, keyLength, objNum, objGen, recursion + 1);
 +      obj.arrayAdd(std::move(obj2));
 +    }
      if (buf1.isEOF()) {
        error(errSyntaxError, getPos(), "End of file inside array");
        if (strict) goto err;
@@@ -97,9 -107,9 +101,9 @@@
      shift();
  
    // dictionary or stream
-   } else if (!simpleOnly && likely(recursion < recursionLimit) && buf1.isCmd("<<")) {
+   } else if (!simpleOnly && buf1.isCmd("<<")) {
      shift(objNum);
 -    obj->initDict(xref);
 +    obj = Object(new Dict(xref));
      while (!buf1.isCmd(">>") && !buf1.isEOF()) {
        if (!buf1.isName()) {
  	error(errSyntaxError, getPos(), "Dictionary key must be a name object");
@@@ -114,8 -124,10 +118,11 @@@
  	  if (strict && buf1.isError()) goto err;
  	  break;
  	}
 -	obj->dictAdd(key, getObj(&obj2, gFalse, fileKey, encAlgorithm, keyLength, objNum, objGen, recursion + 1));
 +	Object obj2 = getObj(gFalse, fileKey, encAlgorithm, keyLength, objNum, objGen, recursion + 1);
+ 	if (unlikely(obj2.isError() && recursion + 1 >= recursionLimit)) {
+ 	  break;
+ 	}
 +	obj.dictAdd(key, std::move(obj2));
        }
      }
      if (buf1.isEOF()) {
diff --cc poppler/Stream.cc
index 03d15de3,4ac91078..e5905fb8
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@@ -290,12 -308,17 +290,17 @@@ Stream *Stream::makeFilter(char *name, 
    } else if (!strcmp(name, "DCTDecode") || !strcmp(name, "DCT")) {
      colorXform = -1;
      if (params->isDict()) {
 -      if (params->dictLookup("ColorTransform", &obj, recursion)->isInt()) {
 +      obj = params->dictLookup("ColorTransform", recursion);
 +      if (obj.isInt()) {
  	colorXform = obj.getInt();
        }
 -      obj.free();
      }
+ #ifdef HAVE_DCT_DECODER
      str = new DCTStream(str, colorXform, dict, recursion);
+ #else
+     error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name);
+     str = new EOFStream(str);
+ #endif
    } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
      pred = 1;
      columns = 1;
@@@ -319,12 -346,19 +324,17 @@@
    } else if (!strcmp(name, "JBIG2Decode")) {
      if (params->isDict()) {
        XRef *xref = params->getDict()->getXRef();
 -      params->dictLookupNF("JBIG2Globals", &obj);
 -      obj.fetch(xref, &globals, recursion);
 +      obj = params->dictLookupNF("JBIG2Globals");
 +      globals = obj.fetch(xref, recursion);
      }
      str = new JBIG2Stream(str, &globals, &obj);
 -    globals.free();
 -    obj.free();
    } else if (!strcmp(name, "JPXDecode")) {
+ #ifdef HAVE_JPX_DECODER
      str = new JPXStream(str);
+ #else
+     error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name);
+     str = new EOFStream(str);
+ #endif
    } else if (!strcmp(name, "Crypt")) {
      if (str->getKind() == strCrypt) {
        str = str->getBaseStream();
diff --cc utils/pdfunite.cc
index dd563857,c32e201b..c223c80b
--- a/utils/pdfunite.cc
+++ b/utils/pdfunite.cc
@@@ -195,24 -258,25 +195,24 @@@ int main (int argc, char *argv[]
  
    // handle OutputIntents, AcroForm, OCProperties & Names
    Object intents;
 +  Object names;
    Object afObj;
    Object ocObj;
 -  Object names;
    if (docs.size() >= 1) {
 -    Object catObj;
 -    docs[0]->getXRef()->getCatalog(&catObj);
 +    Object catObj = docs[0]->getXRef()->getCatalog();
      Dict *catDict = catObj.getDict();
 -    catDict->lookup("OutputIntents", &intents);
 -    catDict->lookupNF("AcroForm", &afObj);
 +    intents = catDict->lookup("OutputIntents");
 +    afObj = catDict->lookupNF("AcroForm");
      Ref *refPage = docs[0]->getCatalog()->getPageRef(1);
-     if (!afObj.isNull()) {
+     if (!afObj.isNull() && refPage) {
        docs[0]->markAcroForm(&afObj, yRef, countRef, 0, refPage->num, refPage->num);
      }
 -    catDict->lookupNF("OCProperties", &ocObj);
 +    ocObj = catDict->lookupNF("OCProperties");
-     if (!ocObj.isNull() && ocObj.isDict()) {
+     if (!ocObj.isNull() && ocObj.isDict() && refPage) {
        docs[0]->markPageObjects(ocObj.getDict(), yRef, countRef, 0, refPage->num, refPage->num);
      }
 -    catDict->lookup("Names", &names);
 +    names = catDict->lookup("Names");
-     if (!names.isNull() && names.isDict()) {
+     if (!names.isNull() && names.isDict() && refPage) {
        docs[0]->markPageObjects(names.getDict(), yRef, countRef, 0, refPage->num, refPage->num);
      }
      if (intents.isArray() && intents.arrayGetLength() > 0) {
commit 23a2f6a2492a0957489eac31b6700b4d68180bdb
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sat Jun 17 17:47:23 2017 +0200

    Break earlier on reaching recursion limit
    
    Bug #101379

diff --git a/poppler/Parser.cc b/poppler/Parser.cc
index 28a54607..8079ca1d 100644
--- a/poppler/Parser.cc
+++ b/poppler/Parser.cc
@@ -13,7 +13,7 @@
 // All changes made under the Poppler project to this file are licensed
 // under GPL version 2 or later
 //
-// Copyright (C) 2006, 2009, 201, 2010, 2013, 2014 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2006, 2009, 201, 2010, 2013, 2014, 2017 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2006 Krzysztof Kowalczyk <kkowalczyk at gmail.com>
 // Copyright (C) 2009 Ilya Gorenbein <igorenbein at finjan.com>
 // Copyright (C) 2012 Hib Eris <hib at hiberis.nl>
@@ -87,8 +87,14 @@ Object *Parser::getObj(Object *obj, GBool simpleOnly,
     inlineImg = 0;
   }
 
+  if (unlikely(recursion >= recursionLimit)) {
+    obj->free();
+    obj->initError();
+    return obj;
+  }
+
   // array
-  if (!simpleOnly && likely(recursion < recursionLimit) && buf1.isCmd("[")) {
+  if (!simpleOnly && buf1.isCmd("[")) {
     shift();
     obj->initArray(xref);
     while (!buf1.isCmd("]") && !buf1.isEOF())
@@ -101,7 +107,7 @@ Object *Parser::getObj(Object *obj, GBool simpleOnly,
     shift();
 
   // dictionary or stream
-  } else if (!simpleOnly && likely(recursion < recursionLimit) && buf1.isCmd("<<")) {
+  } else if (!simpleOnly && buf1.isCmd("<<")) {
     shift(objNum);
     obj->initDict(xref);
     while (!buf1.isCmd(">>") && !buf1.isEOF()) {
@@ -119,6 +125,9 @@ Object *Parser::getObj(Object *obj, GBool simpleOnly,
 	  break;
 	}
 	obj->dictAdd(key, getObj(&obj2, gFalse, fileKey, encAlgorithm, keyLength, objNum, objGen, recursion + 1));
+	if (unlikely(obj2.isError() && recursion + 1 >= recursionLimit)) {
+	  break;
+	}
       }
     }
     if (buf1.isEOF()) {
commit 5323bc8baf9add8c28a0a6970ab94b6386f38d14
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sat Jun 17 12:35:41 2017 +0200

    pdftohmtl: Initialize rotSkewMat
    
    Fixes uninitialized memory read at bug #100314

diff --git a/utils/HtmlFonts.cc b/utils/HtmlFonts.cc
index a12992ec..49376d65 100644
--- a/utils/HtmlFonts.cc
+++ b/utils/HtmlFonts.cc
@@ -156,6 +156,7 @@ HtmlFont::HtmlFont(GfxFont *font, int _size, GfxRGB rgb){
     pos = font_num; 
   if (!DefaultFont) DefaultFont=new GooString(fonts[font_num].name);
 
+  rotSkewMat[0] = rotSkewMat[1] = rotSkewMat[2] = rotSkewMat[3] = 0;
 }
  
 HtmlFont::HtmlFont(const HtmlFont& x){
commit 67159370014e5cb3ef296b256bf410e0468fe71e
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sat Jun 17 12:33:35 2017 +0200

    Remove unused constructor

diff --git a/utils/HtmlFonts.h b/utils/HtmlFonts.h
index 7993c78e..252d5f90 100644
--- a/utils/HtmlFonts.h
+++ b/utils/HtmlFonts.h
@@ -18,7 +18,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2010 OSSD CDAC Mumbai by Leena Chourey (leenac at cdacmumbai.in) and Onkar Potdar (onkar at cdacmumbai.in)
-// Copyright (C) 2010, 2012 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2010, 2012, 2017 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2011 Steven Murdoch <Steven.Murdoch at cl.cam.ac.uk>
 // Copyright (C) 2011 Joshua Richardson <jric at chegg.com>
 // Copyright (C) 2012 Igor Slepchin <igor.slepchin at gmail.com>
@@ -72,7 +72,6 @@ class HtmlFont{
    double rotSkewMat[4]; // only four values needed for rotation and skew
 public:  
 
-   HtmlFont(){FontName=NULL; rotOrSkewed = gFalse;}
    HtmlFont(GfxFont *font,int _size, GfxRGB rgb);
    HtmlFont(const HtmlFont& x);
    HtmlFont& operator=(const HtmlFont& x);
commit d52bba350acb3023ebdba8537854206641cd0998
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sat Jun 17 12:33:06 2017 +0200

    Fix crash in malformed file
    
    Bug #101429

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 279f650d..974b098b 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -5401,7 +5401,7 @@ void AnnotScreen::initialize(PDFDoc *docA, Dict* dict) {
   action = NULL;
   if (dict->lookup("A", &obj1)->isDict()) {
     action = LinkAction::parseAction(&obj1, doc->getCatalog()->getBaseURI());
-    if (action->getKind() == actionRendition && page == 0) {
+    if (action && action->getKind() == actionRendition && page == 0) {
       error (errSyntaxError, -1, "Invalid Rendition action: associated screen annotation without P");
       delete action;
       action = NULL;
commit db254b4b5b1ac2dae46b9fd5ad23af311e481489
Author: Even Rouault <even.rouault at spatialys.com>
Date:   Fri Jun 16 00:21:53 2017 +0200

    Fix crash on broken file
    
    Fixes bug #101366

diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index b9fa6cbd..5502be64 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -37,6 +37,7 @@
 // Copyright (C) 2015 Tamas Szekeres <szekerest at gmail.com>
 // Copyright (C) 2015 Kenji Uno <ku at digitaldolphins.jp>
 // Copyright (C) 2016 Takahiro Hashimoto <kenya888.en at gmail.com>
+// Copyright (C) 2017 Even Rouault <even.rouault at spatialys.com>
 //
 // 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
@@ -2725,7 +2726,7 @@ void SplashOutputDev::type3D1(GfxState *state, double wx, double wy,
   int i, j;
 
   // ignore multiple d0/d1 operators
-  if (t3GlyphStack->haveDx) {
+  if (!t3GlyphStack || t3GlyphStack->haveDx) {
     return;
   }
   t3GlyphStack->haveDx = gTrue;
commit 9fc5ed2176da68442927127bea8c427800eb244c
Author: Hans-Ulrich Jüttner <huj at froreich-bioscientia.de>
Date:   Wed Jun 14 23:19:48 2017 +0200

    FormFieldButton::setState() should check the field isn't readOnly
    
    Bug #101419

diff --git a/poppler/Form.cc b/poppler/Form.cc
index ced3140c..4627a432 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -17,6 +17,7 @@
 // Copyright 2012 Fabio D'Urso <fabiodurso at hotmail.it>
 // Copyright 2015 André Guerreiro <aguerreiro1985 at gmail.com>
 // Copyright 2015 André Esser <bepandre at hotmail.com>
+// Copyright 2017 Hans-Ulrich Jüttner <huj at froreich-bioscientia.de>
 //
 //========================================================================
 
@@ -903,11 +904,6 @@ void FormFieldButton::fillChildrenSiblingsID()
 
 GBool FormFieldButton::setState(char *state)
 {
-  if (readOnly) {
-    error(errInternal, -1, "FormFieldButton::setState called on a readOnly field\n");
-    return gFalse;
-  }
-
   // A check button could behave as a radio button
   // when it's in a set of more than 1 buttons
   if (btype != formButtonRadio && btype != formButtonCheck)
commit 5c9b08a875b07853be6c44e43ff5f7f059df666a
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sat May 27 00:09:17 2017 +0200

    pdfunite: Fix crash with broken documents
    
    Sometimes we can't parse pages so check before accessing them
    
    Thanks to Jiaqi Peng for the report
    
    Fixes bugs #101153 and #101149

diff --git a/utils/pdfunite.cc b/utils/pdfunite.cc
index dfe48bf8..c32e201b 100644
--- a/utils/pdfunite.cc
+++ b/utils/pdfunite.cc
@@ -7,7 +7,7 @@
 // Copyright (C) 2011-2015, 2017 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2012 Arseny Solokha <asolokha at gmx.com>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
-// Copyright (C) 2012, 2014 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2012, 2014, 2017 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
 // Copyright (C) 2013 Hib Eris <hib at hiberis.nl>
 // Copyright (C) 2015 Arthur Stavisky <vovodroid at gmail.com>
@@ -268,15 +268,15 @@ int main (int argc, char *argv[])
     catDict->lookup("OutputIntents", &intents);
     catDict->lookupNF("AcroForm", &afObj);
     Ref *refPage = docs[0]->getCatalog()->getPageRef(1);
-    if (!afObj.isNull()) {
+    if (!afObj.isNull() && refPage) {
       docs[0]->markAcroForm(&afObj, yRef, countRef, 0, refPage->num, refPage->num);
     }
     catDict->lookupNF("OCProperties", &ocObj);
-    if (!ocObj.isNull() && ocObj.isDict()) {
+    if (!ocObj.isNull() && ocObj.isDict() && refPage) {
       docs[0]->markPageObjects(ocObj.getDict(), yRef, countRef, 0, refPage->num, refPage->num);
     }
     catDict->lookup("Names", &names);
-    if (!names.isNull() && names.isDict()) {
+    if (!names.isNull() && names.isDict() && refPage) {
       docs[0]->markPageObjects(names.getDict(), yRef, countRef, 0, refPage->num, refPage->num);
     }
     if (intents.isArray() && intents.arrayGetLength() > 0) {
@@ -353,6 +353,10 @@ int main (int argc, char *argv[])
 
   for (i = 0; i < (int) docs.size(); i++) {
     for (j = 1; j <= docs[i]->getNumPages(); j++) {
+      if (!docs[i]->getCatalog()->getPage(j)) {
+        continue;
+      }
+
       PDFRectangle *cropBox = NULL;
       if (docs[i]->getCatalog()->getPage(j)->isCropped())
         cropBox = docs[i]->getCatalog()->getPage(j)->getCropBox();
commit ff05069f34a00d67cdddb033f6240a3407e90057
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun May 21 23:39:38 2017 +0200

    Poppler 0.55.0

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 58952e47..a79db356 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,7 +22,7 @@ if (ECM_FOUND)
 endif()
 
 set(POPPLER_MAJOR_VERSION "0")
-set(POPPLER_MINOR_VERSION "54")
+set(POPPLER_MINOR_VERSION "55")
 set(POPPLER_MICRO_VERSION "0")
 set(POPPLER_VERSION "${POPPLER_MAJOR_VERSION}.${POPPLER_MINOR_VERSION}.${POPPLER_MICRO_VERSION}")
 
diff --git a/NEWS b/NEWS
index 8f02c6e4..448b06e7 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,19 @@
+Release 0.55.0
+        core:
+         * Fix abort in files with broken Decode arrays. KDE bug #379835
+         * Fix memory leak (and probably logic bug) parsing broken XRef entries. Bug #100775
+         * Fix memory leak when reconstructing broken files. Bug #100776
+         * Minor optimization
+         * Fix regression in GfxIndexedColorSpace::mapColorToBase. Bug #100931
+         * Fix memory leak in error condition
+
+        cpp:
+         * Return nullptr if the page at index can't be fetched. Bug #100981
+
+        build system:
+         * Fail by default if libjpeg is not available
+         * Fail by default if libopenjpeg2/1 is not available
+
 Release 0.54.0
         core:
          * Make XRef reconstruction a bit better. Bug #100509
diff --git a/configure.ac b/configure.ac
index a2cb046d..6e3c6a4e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
 m4_define([poppler_version_major],[0])
-m4_define([poppler_version_minor],[54])
+m4_define([poppler_version_minor],[55])
 m4_define([poppler_version_micro],[0])
 m4_define([poppler_version],[poppler_version_major.poppler_version_minor.poppler_version_micro])
 
diff --git a/cpp/Doxyfile b/cpp/Doxyfile
index 665af301..d29e6a5a 100644
--- a/cpp/Doxyfile
+++ b/cpp/Doxyfile
@@ -31,7 +31,7 @@ PROJECT_NAME           = "Poppler CPP"
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 0.54.0
+PROJECT_NUMBER         = 0.55.0
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
 # base path where the generated documentation will be put.
diff --git a/qt4/src/Doxyfile b/qt4/src/Doxyfile
index 98d8f8d7..f756dce9 100644
--- a/qt4/src/Doxyfile
+++ b/qt4/src/Doxyfile
@@ -31,7 +31,7 @@ PROJECT_NAME           = "Poppler Qt4 "
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 0.54.0
+PROJECT_NUMBER         = 0.55.0
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
 # base path where the generated documentation will be put.
diff --git a/qt5/src/Doxyfile b/qt5/src/Doxyfile
index 1cd97d03..c5c873a3 100644
--- a/qt5/src/Doxyfile
+++ b/qt5/src/Doxyfile
@@ -31,7 +31,7 @@ PROJECT_NAME           = "Poppler Qt5"
 # This could be handy for archiving the generated documentation or
 # if some version control system is used.
 
-PROJECT_NUMBER         = 0.54.0
+PROJECT_NUMBER         = 0.55.0
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
 # base path where the generated documentation will be put.
commit 680b3f6b80e6d342a6b6e3fe8f1953857784f737
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun May 21 23:20:56 2017 +0200

    Update (C)

diff --git a/poppler/Object.h b/poppler/Object.h
index e55ba687..18c4558c 100644
--- a/poppler/Object.h
+++ b/poppler/Object.h
@@ -15,7 +15,7 @@
 //
 // Copyright (C) 2007 Julien Rebetez <julienr at svn.gnome.org>
 // Copyright (C) 2008 Kees Cook <kees at outflux.net>
-// Copyright (C) 2008, 2010 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2008, 2010, 2017 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2009 Jakub Wilk <jwilk at jwilk.net>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
 // Copyright (C) 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
commit 0bf38541443cb8dee4d9a5197fdfcf91f6043a2d
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun May 21 23:20:38 2017 +0200

    Don't forget to ship this file ^_^

diff --git a/Makefile.am b/Makefile.am
index 9540b6ad..bf878bad 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -98,6 +98,7 @@ EXTRA_DIST +=							\
 	cmake/modules/PopplerDefaults.cmake			\
 	cmake/modules/PopplerMacros.cmake			\
 	cmake/modules/FindLIBOPENJPEG.cmake			\
+	cmake/modules/FindLIBOPENJPEG2.cmake			\
 	config.h.cmake						\
 	poppler-cairo.pc.cmake					\
 	poppler/poppler-config.h.cmake				\
commit aa03a71c3a1127cffd19bb0f596c4b361a7f2269
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun May 21 22:37:23 2017 +0200

    Fix abort in files with broken Decode arrays
    
    Fixes KDE bug #379835

diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index 2c81dfbe..b17925f4 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -5311,24 +5311,30 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(GfxResources *res, int typeA, Di
   obj1.free();
   if (dict->lookup("Decode", &obj1)->isArray() &&
       obj1.arrayGetLength() >= 6) {
-    xMin = obj1.arrayGet(0, &obj2)->getNum();
+    bool decodeOk = true;
+    xMin = obj1.arrayGet(0, &obj2)->getNum(&decodeOk);
     obj2.free();
-    xMax = obj1.arrayGet(1, &obj2)->getNum();
+    xMax = obj1.arrayGet(1, &obj2)->getNum(&decodeOk);
     obj2.free();
     xMul = (xMax - xMin) / (pow(2.0, coordBits) - 1);
-    yMin = obj1.arrayGet(2, &obj2)->getNum();
+    yMin = obj1.arrayGet(2, &obj2)->getNum(&decodeOk);
     obj2.free();
-    yMax = obj1.arrayGet(3, &obj2)->getNum();
+    yMax = obj1.arrayGet(3, &obj2)->getNum(&decodeOk);
     obj2.free();
     yMul = (yMax - yMin) / (pow(2.0, coordBits) - 1);
     for (i = 0; 5 + 2*i < obj1.arrayGetLength() && i < gfxColorMaxComps; ++i) {
-      cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum();
+      cMin[i] = obj1.arrayGet(4 + 2*i, &obj2)->getNum(&decodeOk);
       obj2.free();
-      cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum();
+      cMax[i] = obj1.arrayGet(5 + 2*i, &obj2)->getNum(&decodeOk);
       obj2.free();
       cMul[i] = (cMax[i] - cMin[i]) / (double)((1 << compBits) - 1);
     }
     nComps = i;
+
+    if (!decodeOk) {
+      error(errSyntaxWarning, -1, "Missing or invalid Decode array in shading dictionary");
+      goto err2;
+    }
   } else {
     error(errSyntaxWarning, -1, "Missing or invalid Decode array in shading dictionary");
     goto err2;
diff --git a/poppler/Object.h b/poppler/Object.h
index e3f8f378..e55ba687 100644
--- a/poppler/Object.h
+++ b/poppler/Object.h
@@ -208,6 +208,13 @@ public:
   // Where the exact value of integers up to 2^63 is required, use isInt64()/getInt64().
   double getNum() { OBJECT_3TYPES_CHECK(objInt, objInt64, objReal);
     return type == objInt ? (double)intg : type == objInt64 ? (double)int64g : real; }
+  double getNum(bool *ok) {
+    if (unlikely(type != objInt && type != objInt64 && type != objReal)) {
+      *ok = false;
+      return 0.;
+    }
+    return type == objInt ? (double)intg : type == objInt64 ? (double)int64g : real;
+  }
   GooString *getString() { OBJECT_TYPE_CHECK(objString); return string; }
   // After takeString() the only method that should be called for the object is free()
   // because the object it's not expected to have a NULL string.
commit 65c5a5266462244130f110599ac5d1011a04216e
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun May 21 18:42:15 2017 +0200

    Fail by default if libopenjpeg2/1 is not available
    
    You can "force" to use the unmaintained JPX decoder or none at all

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 15e01222..58952e47 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,7 +37,7 @@ option(BUILD_CPP_TESTS "Whether compile the CPP test programs." ON)
 option(ENABLE_SPLASH "Build the Splash graphics backend." ON)
 option(ENABLE_UTILS "Compile poppler command line utils." ON)
 option(ENABLE_CPP "Compile poppler cpp wrapper." ON)
-set(ENABLE_LIBOPENJPEG "auto" CACHE STRING "Use libopenjpeg for JPX streams. Possible values: auto, openjpeg1, openjpeg2. 'auto' prefers openjpeg2 over openjpeg1 if both are available. Unset to not use openjpeg.")
+set(ENABLE_LIBOPENJPEG "auto" CACHE STRING "Use libopenjpeg for JPX streams. Possible values: auto, openjpeg1, openjpeg2, unmaintained, none. 'auto' prefers openjpeg2 over openjpeg1 if both are available. 'unmaintained' gives you the internal unmaintained decoder. Use at your own risk. 'none' compiles no JPX decoder at all. Default: auto")
 set(ENABLE_CMS "auto" CACHE STRING "Use color management system. Possible values: auto, lcms1, lcms2. 'auto' prefers lcms2 over lcms1 if both are available. Unset to disable color management system.")
 set(ENABLE_DCTDECODER "libjpeg" CACHE STRING "Use libjpeg for DCT streams. Possible values: libjpeg, unmaintained, none. will use libjpeg if available or fail if not. 'unmaintained' gives you the internal unmaintained decoder. Use at your own risk. 'none' compiles no DCT decoder at all. Default: libjpeg")
 option(ENABLE_LIBCURL "Build libcurl based HTTP support." OFF)
@@ -191,15 +191,35 @@ if(ENABLE_LIBOPENJPEG STREQUAL "auto")
     find_package(LIBOPENJPEG)
     set(USE_OPENJPEG1 ${LIBOPENJPEG_FOUND})
     set(WITH_OPENJPEG ${LIBOPENJPEG_FOUND})  
+    if(NOT LIBOPENJPEG_FOUND)
+      message(FATAL_ERROR "Install libopenjpeg2 or libopenjpeg1 before trying to build poppler. You can also decide to use the internal unmaintained JPX decoder or none at all.")
+    endif()
   endif()
+  set(HAVE_JPX_DECODER ON)
 elseif(ENABLE_LIBOPENJPEG STREQUAL "openjpeg1")
   find_package(LIBOPENJPEG)
   set(USE_OPENJPEG1 ${LIBOPENJPEG_FOUND})
   set(WITH_OPENJPEG ${LIBOPENJPEG_FOUND})
+  if(NOT LIBOPENJPEG_FOUND)
+    message(FATAL_ERROR "Install libopenjpeg1 before trying to build poppler. You can also decide to use the internal unmaintained JPX decoder or none at all.")
+  endif()
+  set(HAVE_JPX_DECODER ON)
 elseif(ENABLE_LIBOPENJPEG STREQUAL "openjpeg2")
   find_package(LIBOPENJPEG2)
   set(USE_OPENJPEG2 ${LIBOPENJPEG2_FOUND})
   set(WITH_OPENJPEG ${LIBOPENJPEG2_FOUND})
+  if(NOT LIBOPENJPEG2_FOUND)
+    message(FATAL_ERROR "Install libopenjpeg2 before trying to build poppler. You can also decide to use the internal unmaintained JPX decoder or none at all.")
+  endif()
+  set(HAVE_JPX_DECODER ON)
+elseif(ENABLE_LIBOPENJPEG STREQUAL "unmaintained")
+  set(WITH_OPENJPEG OFF)
+  set(HAVE_JPX_DECODER ON)
+elseif(ENABLE_LIBOPENJPEG STREQUAL "none")
+  set(WITH_OPENJPEG OFF)
+  set(HAVE_JPX_DECODER OFF)
+else()
+  message(FATAL_ERROR "Invalid ENABLE_LIBOPENJPEG value: ${ENABLE_LIBOPENJPEG}")
 endif()
 set(ENABLE_LIBOPENJPEG "${WITH_OPENJPEG}")
 if(ENABLE_CMS STREQUAL "auto")
@@ -797,6 +817,10 @@ if(ENABLE_ZLIB_UNCOMPRESS)
   message("Warning: Using zlib is not totally safe")
 endif(ENABLE_ZLIB_UNCOMPRESS)
 
-if(NOT WITH_OPENJPEG)
+if(NOT WITH_OPENJPEG AND HAVE_JPX_DECODER)
   message("Warning: Using libopenjpeg2 is recommended. The internal JPX decoder is unmaintained.")
-endif(NOT WITH_OPENJPEG)
+endif()
+
+if(NOT HAVE_JPX_DECODER)
+  message("Warning: You're not compiling any JPX decoder. Some files will fail to display properly.")
+endif()
diff --git a/config.h.cmake b/config.h.cmake
index db7bfcb3..4a4da624 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -33,6 +33,9 @@
 /* Do we have any DCT decoder?. */
 #cmakedefine HAVE_DCT_DECODER 1
 
+/* Do we have any JPX decoder?. */
+#cmakedefine HAVE_JPX_DECODER 1
+
 /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
    */
 #cmakedefine HAVE_DIRENT_H 1
diff --git a/configure.ac b/configure.ac
index 899c45dc..a2cb046d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -201,8 +201,8 @@ dnl ##### Test for libopenjpeg. Versions prior to 1.4 do not provide a pkgconfig
 openjpeg1="no"
 openjpeg2="no"
 AC_ARG_ENABLE(libopenjpeg,
-	      AC_HELP_STRING([--enable-libopenjpeg=@<:@auto/openjpeg1/openjpeg2/none@:>@],
-                             [Use openjpeg for JPEG2000 images. 'auto' prefers openjpeg2 over openjpeg1 if both are available [[default=auto]]]),
+	      AC_HELP_STRING([--enable-libopenjpeg=@<:@auto/openjpeg1/openjpeg2/unmaintained/none@:>@],
+                             [Use openjpeg for JPEG2000 images. 'auto' prefers openjpeg2 over openjpeg1 if both are available. 'unmaintained' gives you the internal unmaintained decoder. Use at your own risk. 'none' compiles no JPX decoder at all. [[default=auto]]]),
               [enable_libopenjpeg=$enableval],
               [enable_libopenjpeg="auto"])
 
@@ -258,10 +258,27 @@ if test x$openjpeg1 = xyes || test x$openjpeg2 = xyes; then
        [AC_DEFINE(WITH_OPENJPEG_IGNORE_PCLR_CMAP_CDEF_FLAG, 1, [OpenJPEG with the OPJ_DPARAMETERS_IGNORE_PCLR_CMAP_CDEF_FLAG flag.])],
        [])
       ])
+  have_jpx_decoder=yes
+  AC_DEFINE(HAVE_JPX_DECODER)
 else
-  enable_libopenjpeg=no
+  if test x$enable_libopenjpeg = xunmaintained; then
+    enable_libopenjpeg=no
+    have_jpx_decoder=yes
+    AC_DEFINE(HAVE_JPX_DECODER)
+  elif test x$enable_libopenjpeg = xnone; then
+    enable_libopenjpeg=no
+    have_jpx_decoder=no
+  else
+    if test x$enable_libopenjpeg = xopenjpeg2 || test x$enable_libopenjpeg = xopenjpeg1 || test x$enable_libopenjpeg = xauto; then
+      AC_MSG_ERROR([Install libopenjpeg2 or libopenjpeg1 before trying to build poppler. You can also decide to use the internal unmaintained JPX decoder or none at all. See --help.])
+    else
+      AC_MSG_ERROR([Invalid --enable-libopenjpeg value. See --help.])
+    fi
+  fi
 fi
 
+AH_TEMPLATE([HAVE_JPX_DECODER], [Do we have any JPX decoder?.])
+
 dnl Test for NSS
 AC_ARG_ENABLE(libnss,
         AC_HELP_STRING([--disable-libnss],
@@ -1108,6 +1125,10 @@ if test x$enable_zlib_uncompress != xno; then
 	echo "  Warning: Using zlib for decompression is not totally safe"
 fi
 
-if test x$enable_libopenjpeg != xyes; then
+if test x$enable_libopenjpeg != xyes -a x$have_jpx_decoder = xyes; then
 	echo "  Warning: Using libopenjpeg2 is recommended. The internal JPX decoder is unmaintained."
 fi
+
+if test x$have_jpx_decoder = xno; then
+	echo "  Warning: You're not compiling any JPX decoder. Some files will fail to display properly."
+fi
diff --git a/poppler/Stream.cc b/poppler/Stream.cc
index d1abf3ff..4ac91078 100644
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@ -353,7 +353,12 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params, int recursio
     globals.free();
     obj.free();
   } else if (!strcmp(name, "JPXDecode")) {
+#ifdef HAVE_JPX_DECODER
     str = new JPXStream(str);
+#else
+    error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name);
+    str = new EOFStream(str);
+#endif
   } else if (!strcmp(name, "Crypt")) {
     if (str->getKind() == strCrypt) {
       str = str->getBaseStream();
commit ea6d3200ae26775dcc26ed80fad18ca51e7f7f07
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun May 21 18:08:41 2017 +0200

    Fix openjpeg text
    
    We've prefered openjpeg2 over 1 for a while

diff --git a/CMakeLists.txt b/CMakeLists.txt
index bb663a1e..15e01222 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -37,7 +37,7 @@ option(BUILD_CPP_TESTS "Whether compile the CPP test programs." ON)
 option(ENABLE_SPLASH "Build the Splash graphics backend." ON)
 option(ENABLE_UTILS "Compile poppler command line utils." ON)
 option(ENABLE_CPP "Compile poppler cpp wrapper." ON)
-set(ENABLE_LIBOPENJPEG "auto" CACHE STRING "Use libopenjpeg for JPX streams. Possible values: auto, openjpeg1, openjpeg2. 'auto' prefers openjpeg1 over openjpeg2 if both are available. Unset to not use openjpeg.")
+set(ENABLE_LIBOPENJPEG "auto" CACHE STRING "Use libopenjpeg for JPX streams. Possible values: auto, openjpeg1, openjpeg2. 'auto' prefers openjpeg2 over openjpeg1 if both are available. Unset to not use openjpeg.")
 set(ENABLE_CMS "auto" CACHE STRING "Use color management system. Possible values: auto, lcms1, lcms2. 'auto' prefers lcms2 over lcms1 if both are available. Unset to disable color management system.")
 set(ENABLE_DCTDECODER "libjpeg" CACHE STRING "Use libjpeg for DCT streams. Possible values: libjpeg, unmaintained, none. will use libjpeg if available or fail if not. 'unmaintained' gives you the internal unmaintained decoder. Use at your own risk. 'none' compiles no DCT decoder at all. Default: libjpeg")
 option(ENABLE_LIBCURL "Build libcurl based HTTP support." OFF)
diff --git a/configure.ac b/configure.ac
index 6f8eef97..899c45dc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -202,7 +202,7 @@ openjpeg1="no"
 openjpeg2="no"
 AC_ARG_ENABLE(libopenjpeg,
 	      AC_HELP_STRING([--enable-libopenjpeg=@<:@auto/openjpeg1/openjpeg2/none@:>@],
-                             [Use openjpeg for JPEG2000 images. 'auto' prefers openjpeg1 over openjpeg2 if both are available due to regressions in openjpeg2 [[default=auto]]]),
+                             [Use openjpeg for JPEG2000 images. 'auto' prefers openjpeg2 over openjpeg1 if both are available [[default=auto]]]),
               [enable_libopenjpeg=$enableval],
               [enable_libopenjpeg="auto"])
 
commit b286a6b5b1a63563263072305da04604cb022488
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun May 21 17:45:00 2017 +0200

    Fail by default if libjpeg is not available
    
    You can "force" to use the unmaintained DCT decoder or none at all

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b3ff39de..bb663a1e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -39,6 +39,7 @@ option(ENABLE_UTILS "Compile poppler command line utils." ON)
 option(ENABLE_CPP "Compile poppler cpp wrapper." ON)
 set(ENABLE_LIBOPENJPEG "auto" CACHE STRING "Use libopenjpeg for JPX streams. Possible values: auto, openjpeg1, openjpeg2. 'auto' prefers openjpeg1 over openjpeg2 if both are available. Unset to not use openjpeg.")
 set(ENABLE_CMS "auto" CACHE STRING "Use color management system. Possible values: auto, lcms1, lcms2. 'auto' prefers lcms2 over lcms1 if both are available. Unset to disable color management system.")
+set(ENABLE_DCTDECODER "libjpeg" CACHE STRING "Use libjpeg for DCT streams. Possible values: libjpeg, unmaintained, none. will use libjpeg if available or fail if not. 'unmaintained' gives you the internal unmaintained decoder. Use at your own risk. 'none' compiles no DCT decoder at all. Default: libjpeg")
 option(ENABLE_LIBCURL "Build libcurl based HTTP support." OFF)
 option(ENABLE_ZLIB "Build with zlib." ON)
 option(ENABLE_ZLIB_UNCOMPRESS "Use zlib to uncompress flate streams (not totally safe)." OFF)
@@ -109,9 +110,22 @@ macro_optional_find_package(JPEG)
 macro_optional_find_package(PNG)
 macro_optional_find_package(TIFF)
 macro_optional_find_package(NSS3)
-if(JPEG_FOUND)
-  set(ENABLE_LIBJPEG ${JPEG_FOUND})
-endif(JPEG_FOUND)
+if(ENABLE_DCTDECODER STREQUAL "libjpeg")
+  if(JPEG_FOUND)
+    set(ENABLE_LIBJPEG ${JPEG_FOUND})
+  else()
+    message(FATAL_ERROR "Install libjpeg before trying to build poppler. You can also decide to use the internal unmaintained DCT decoder or none at all.")
+  endif()
+  set(HAVE_DCT_DECODER ON)
+elseif(ENABLE_DCTDECODER STREQUAL "unmaintained")
+  set(ENABLE_LIBJPEG OFF)
+  set(HAVE_DCT_DECODER ON)
+elseif(ENABLE_DCTDECODER STREQUAL "none")
+  set(ENABLE_LIBJPEG OFF)
+  set(HAVE_DCT_DECODER OFF)
+else()
+  message(FATAL_ERROR "Invalid ENABLE_DCTDECODER value.")
+endif()
 macro_optional_find_package(Qt4)
 if(${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}.${CMAKE_PATCH_VERSION} VERSION_GREATER 2.8.7)
   find_package(Qt5Core)
@@ -249,7 +263,6 @@ if (NSS3_FOUND)
 endif(NSS3_FOUND)
 if(JPEG_FOUND)
   include_directories(${JPEG_INCLUDE_DIR})
-  set(ENABLE_LIBJPEG ON)
 endif(JPEG_FOUND)
 if(PNG_FOUND)
   include_directories(${PNG_INCLUDE_DIR})
@@ -772,9 +785,13 @@ if(USE_FIXEDPOINT AND USE_FLOAT)
   message("Warning: Single precision and fixed point options should not be enabled at the same time")
 endif(USE_FIXEDPOINT AND USE_FLOAT)
 
-if(NOT ENABLE_LIBJPEG)
+if(NOT ENABLE_LIBJPEG AND HAVE_DCT_DECODER)
   message("Warning: Using libjpeg is recommended. The internal DCT decoder is unmaintained.")
-endif(NOT ENABLE_LIBJPEG)
+endif()
+
+if(NOT HAVE_DCT_DECODER)
+  message("Warning: You're not compiling any DCT decoder. Some files will fail to display properly.")
+endif()
 
 if(ENABLE_ZLIB_UNCOMPRESS)
   message("Warning: Using zlib is not totally safe")
diff --git a/config.h.cmake b/config.h.cmake
index 7988b74e..db7bfcb3 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -30,6 +30,9 @@
 /* Use cairo for rendering. */
 #cmakedefine HAVE_CAIRO 1
 
+/* Do we have any DCT decoder?. */
+#cmakedefine HAVE_DCT_DECODER 1
+
 /* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'.
    */
 #cmakedefine HAVE_DIRENT_H 1
diff --git a/configure.ac b/configure.ac
index 050a8912..6f8eef97 100644
--- a/configure.ac
+++ b/configure.ac
@@ -425,14 +425,15 @@ fi
 
 AM_CONDITIONAL(BUILD_LIBCURL, test x$enable_libcurl = xyes)
 
-dnl Test for libjpeg
-AC_ARG_ENABLE(libjpeg,
-	      AC_HELP_STRING([--disable-libjpeg],
-	                     [Don't build against libjpeg.]),
-              enable_libjpeg=$enableval,
-              enable_libjpeg="try")
+dnl Test for dct decoder
+AC_ARG_ENABLE(dctdecoder,
+	      AC_HELP_STRING([--enable-dctdecoder=@<:@libjpeg/unmaintained/none@:>@],
+                             [Decides which DCT decoder to use. 'libjpeg' will use libjpeg if available or fail if not. 'unmaintained' gives you the internal unmaintained decoder. Use at your own risk. 'none' compiles no DCT decoder at all. [[default=libjpeg]]]),
+              [dctdecoder=$enableval],
+              [dctdecoder="libjpeg"])
+
 AC_ARG_VAR([LIBJPEG_CFLAGS], [C compiler flags for LIBJPEG])
-if test x$enable_libjpeg != xno; then
+if test x$dctdecoder = x"libjpeg"; then
 
   dnl
   dnl POPPLER_FIND_JPEG uses "USER_INCLUDES" and "USER_LIBS"
@@ -488,11 +489,28 @@ if test x$enable_libjpeg != xno; then
   AC_SUBST(LIBJPEG_CFLAGS)
   USER_INCLUDES="$ac_save_USER_INCLUDES"
   USER_LDFLAGS="$ac_save_USER_LDFLAGS"
+
+  if test x$enable_libjpeg != x"yes"; then
+    AC_MSG_ERROR([Install libjpeg before trying to build poppler. You can also decide to use the internal unmaintained DCT decoder or none at all. See --help.])
+  fi
+  have_dct_decoder="yes"
+  AC_DEFINE(HAVE_DCT_DECODER)
+elif test x$dctdecoder = x"unmaintained"; then
+  enable_libjpeg="no"
+  have_dct_decoder="yes"
+  AC_DEFINE(HAVE_DCT_DECODER)
+elif test x$dctdecoder = x"none"; then
+  enable_libjpeg="no"
+  have_dct_decoder="no"
+else
+    AC_MSG_ERROR([Invalid --enable-dctdecoder value. See --help.])
 fi
 
+AH_TEMPLATE([HAVE_DCT_DECODER], [Do we have any DCT decoder?.])
+
 AM_CONDITIONAL(BUILD_LIBJPEG, test x$enable_libjpeg = xyes)
 AH_TEMPLATE([ENABLE_LIBJPEG],
-            [Use libjpeg instead of builtin jpeg decoder.])
+            [Use libjpeg instead of builtin unmaintained jpeg decoder.])
 
 dnl Test for libpng
 AC_ARG_ENABLE(libpng,
@@ -1078,10 +1096,14 @@ if test x$enable_single_precision = xyes -a x$enable_fixedpoint = xyes; then
 	echo "  Warning: Single precision and fixed point options should not be enabled at the same time"
 fi
 
-if test x$enable_libjpeg != xyes; then
+if test x$enable_libjpeg != xyes -a x$have_dct_decoder = xyes; then
 	echo "  Warning: Using libjpeg is recommended. The internal DCT decoder is unmaintained."
 fi
 
+if test x$have_dct_decoder = xno; then
+	echo "  Warning: You're not compiling any DCT decoder. Some files will fail to display properly."
+fi
+
 if test x$enable_zlib_uncompress != xno; then
 	echo "  Warning: Using zlib for decompression is not totally safe"
 fi
diff --git a/poppler/Stream.cc b/poppler/Stream.cc
index 4a9babe4..d1abf3ff 100644
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@ -14,7 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Jeff Muizelaar <jeff at infidigm.net>
-// Copyright (C) 2006-2010, 2012-2014, 2016 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2006-2010, 2012-2014, 2016, 2017 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2007 Krzysztof Kowalczyk <kkowalczyk at gmail.com>
 // Copyright (C) 2008 Julien Rebetez <julien at fhtagn.net>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
@@ -313,7 +313,12 @@ Stream *Stream::makeFilter(char *name, Stream *str, Object *params, int recursio
       }
       obj.free();
     }
+#ifdef HAVE_DCT_DECODER
     str = new DCTStream(str, colorXform, dict, recursion);
+#else
+    error(errSyntaxError, getPos(), "Unknown filter '{0:s}'", name);
+    str = new EOFStream(str);
+#endif
   } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) {
     pred = 1;
     columns = 1;
commit 96ff78d63d2173671d07f62910b1d85c5fc509ff
Author: Albert Astals Cid <aacid at kde.org>
Date:   Wed May 10 11:20:56 2017 +0200

    cpp: Return nullptr if the page at index can't be fethed
    
    That is the same of what the glib/qt frontends do.
    
    Bug #100981

diff --git a/cpp/poppler-document.cpp b/cpp/poppler-document.cpp
index 35bbfa2a..998a836d 100644
--- a/cpp/poppler-document.cpp
+++ b/cpp/poppler-document.cpp
@@ -25,6 +25,7 @@
 
 #include "poppler-document-private.h"
 #include "poppler-embedded-file-private.h"
+#include "poppler-page-private.h"
 #include "poppler-private.h"
 #include "poppler-toc-private.h"
 
@@ -916,7 +917,17 @@ page* document::create_page(const ustring &label) const
  */
 page* document::create_page(int index) const
 {
-    return index >= 0 && index < d->doc->getNumPages() ? new page(d, index) : 0;
+    if (index >= 0 && index < d->doc->getNumPages()) {
+        page *p = new page(d, index);
+        if (p->d->page) {
+            return p;
+        } else {
+            delete p;
+            return nullptr;
+        }
+    } else {
+        return nullptr;
+    }
 }
 
 /**
diff --git a/cpp/tests/poppler-dump.cpp b/cpp/tests/poppler-dump.cpp
index 1185971b..398a5004 100644
--- a/cpp/tests/poppler-dump.cpp
+++ b/cpp/tests/poppler-dump.cpp
@@ -301,16 +301,24 @@ static void print_embedded_files(poppler::document *doc)
 
 static void print_page(poppler::page *p)
 {
-    std::cout << std::setw(out_width) << "Rect" << ": " << p->page_rect() << std::endl;
-    std::cout << std::setw(out_width) << "Label" << ": " << p->label() << std::endl;
-    std::cout << std::setw(out_width) << "Duration" << ": " << p->duration() << std::endl;
-    std::cout << std::setw(out_width) << "Orientation" << ": " << out_page_orientation(p->orientation()) << std::endl;
+    if (p) {
+        std::cout << std::setw(out_width) << "Rect" << ": " << p->page_rect() << std::endl;
+        std::cout << std::setw(out_width) << "Label" << ": " << p->label() << std::endl;
+        std::cout << std::setw(out_width) << "Duration" << ": " << p->duration() << std::endl;
+        std::cout << std::setw(out_width) << "Orientation" << ": " << out_page_orientation(p->orientation()) << std::endl;
+    } else {
+        std::cout << std::setw(out_width) << "Broken Page. Could not be parsed" << std::endl;
+    }
     std::cout << std::endl;
 }
 
 static void print_page_text(poppler::page *p)
 {
-    std::cout << p->text(p->page_rect(), show_text_layout) << std::endl;
+    if (p) {
+        std::cout << p->text(p->page_rect(), show_text_layout) << std::endl;
+    } else {
+        std::cout << std::setw(out_width) << "Broken Page. Could not be parsed" << std::endl;
+    }
     std::cout << std::endl;
 }
 


More information about the poppler mailing list