From 2e1d9e4b61defeb036036c15ec39ecea28008c88 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Feb 16 2021 13:45:57 +0000 Subject: import poppler-0.66.0-27.module+el8.3.1+9673+ebe746fd --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0c42acf --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +SOURCES/poppler-0.66.0.tar.xz +SOURCES/poppler-test-2009-05-13_0d2bfd4af4c76a3bac27ccaff793d9129df7b57a.tar.xz diff --git a/.poppler.metadata b/.poppler.metadata new file mode 100644 index 0000000..d64dede --- /dev/null +++ b/.poppler.metadata @@ -0,0 +1,2 @@ +95f58069ddbeb7db9bee68873266a5dc8aaaef96 SOURCES/poppler-0.66.0.tar.xz +b58229322eb8f44a2bb1d98114b9fa3dfbef6a0a SOURCES/poppler-test-2009-05-13_0d2bfd4af4c76a3bac27ccaff793d9129df7b57a.tar.xz diff --git a/SOURCES/poppler-0.30.0-rotated-words-selection.patch b/SOURCES/poppler-0.30.0-rotated-words-selection.patch new file mode 100644 index 0000000..59524c9 --- /dev/null +++ b/SOURCES/poppler-0.30.0-rotated-words-selection.patch @@ -0,0 +1,285 @@ +From 0ab1f29d4ce315b0fca260c0e0f3007024d00342 Mon Sep 17 00:00:00 2001 +From: Marek Kasik +Date: Tue, 28 Jan 2014 15:13:24 +0100 +Subject: [PATCH] TextOutputDev: Respect orientation when selecting words + +Take rotation into account when visiting selection. +This doesn't fix all problems (there are still problems +on line and block levels). + +https://bugs.freedesktop.org/show_bug.cgi?id=16619 +--- + poppler/TextOutputDev.cc | 193 ++++++++++++++++++++++++++++++++++++----------- + 1 file changed, 150 insertions(+), 43 deletions(-) + +diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc +index 7c2ca78..e93908c 100644 +--- a/poppler/TextOutputDev.cc ++++ b/poppler/TextOutputDev.cc +@@ -178,6 +178,12 @@ + #define combMaxMidDelta 0.3 + #define combMaxBaseDelta 0.4 + ++// Returns whether x is between a and b or equal to a or b. ++// a and b don't need to be sorted. ++#define XBetweenAB(x,a,b) (!(((x) > (a) && (x) > (b)) || \ ++ ((x) < (a) && (x) < (b))) ? \ ++ gTrue : gFalse) ++ + static int reorderText(Unicode *text, int len, UnicodeMap *uMap, GBool primaryLR, GooString *s, Unicode* u) { + char lre[8], rle[8], popdf[8], buf[8]; + int lreLen = 0, rleLen = 0, popdfLen = 0, n; +@@ -4411,11 +4417,37 @@ void TextSelectionSizer::visitLine (TextLine *line, + PDFRectangle *rect; + double x1, y1, x2, y2, margin; + +- margin = (line->yMax - line->yMin) / 8; +- x1 = line->edge[edge_begin]; +- y1 = line->yMin - margin; +- x2 = line->edge[edge_end]; +- y2 = line->yMax + margin; ++ switch (line->rot) { ++ default: ++ case 0: ++ margin = (line->yMax - line->yMin) / 8; ++ x1 = line->edge[edge_begin]; ++ x2 = line->edge[edge_end]; ++ y1 = line->yMin - margin; ++ y2 = line->yMax + margin; ++ break; ++ case 1: ++ margin = (line->xMax - line->xMin) / 8; ++ x1 = line->xMin - margin; ++ x2 = line->xMax + margin; ++ y1 = line->edge[edge_begin]; ++ y2 = line->edge[edge_end]; ++ break; ++ case 2: ++ margin = (line->yMax - line->yMin) / 8; ++ x1 = line->edge[edge_end]; ++ x2 = line->edge[edge_begin]; ++ y1 = line->yMin - margin; ++ y2 = line->yMax + margin; ++ break; ++ case 3: ++ margin = (line->xMax - line->xMin) / 8; ++ x1 = line->xMin - margin; ++ x2 = line->xMax + margin; ++ y1 = line->edge[edge_end]; ++ y2 = line->edge[edge_begin]; ++ break; ++ } + + rect = new PDFRectangle (floor (x1 * scale), + floor (y1 * scale), +@@ -4499,19 +4531,56 @@ void TextSelectionPainter::visitLine (TextLine *line, + { + double x1, y1, x2, y2, margin; + +- margin = (line->yMax - line->yMin) / 8; +- x1 = floor (line->edge[edge_begin]); +- y1 = floor (line->yMin - margin); +- x2 = ceil (line->edge[edge_end]); +- y2 = ceil (line->yMax + margin); ++ switch (line->rot) { ++ default: ++ case 0: ++ margin = (line->yMax - line->yMin) / 8; ++ x1 = line->edge[edge_begin]; ++ x2 = line->edge[edge_end]; ++ y1 = line->yMin - margin; ++ y2 = line->yMax + margin; ++ break; ++ case 1: ++ margin = (line->xMax - line->xMin) / 8; ++ x1 = line->xMin - margin; ++ x2 = line->xMax + margin; ++ y1 = line->edge[edge_begin]; ++ y2 = line->edge[edge_end]; ++ break; ++ case 2: ++ margin = (line->yMax - line->yMin) / 8; ++ x1 = line->edge[edge_end]; ++ x2 = line->edge[edge_begin]; ++ y1 = line->yMin - margin; ++ y2 = line->yMax + margin; ++ break; ++ case 3: ++ margin = (line->xMax - line->xMin) / 8; ++ x1 = line->xMin - margin; ++ x2 = line->xMax + margin; ++ y1 = line->edge[edge_end]; ++ y2 = line->edge[edge_begin]; ++ break; ++ } ++ ++ ctm.transform(x1, y1, &x1, &y1); ++ ctm.transform(x2, y2, &x2, &y2); + +- ctm.transform(line->edge[edge_begin], line->yMin - margin, &x1, &y1); +- ctm.transform(line->edge[edge_end], line->yMax + margin, &x2, &y2); ++ if (x1 < x2) { ++ x1 = floor (x1); ++ x2 = ceil (x2); ++ } else { ++ x1 = ceil (x1); ++ x2 = floor (x2); ++ } + +- x1 = floor (x1); +- y1 = floor (y1); +- x2 = ceil (x2); +- y2 = ceil (y2); ++ if (y1 < y2) { ++ y1 = floor (y1); ++ y2 = ceil (y2); ++ } else { ++ y1 = ceil (y1); ++ y2 = floor (y2); ++ } + + ictm.transform(x1, y1, &x1, &y1); + ictm.transform(x2, y2, &x2, &y2); +@@ -4589,17 +4658,27 @@ void TextWord::visitSelection(TextSelectionVisitor *visitor, + SelectionStyle style) + { + int i, begin, end; +- double mid; ++ double mid, s1, s2; ++ ++ if (rot == 0 || rot == 2) { ++ s1 = selection->x1; ++ s2 = selection->x2; ++ } else { ++ s1 = selection->y1; ++ s2 = selection->y2; ++ } + + begin = len; + end = 0; + for (i = 0; i < len; i++) { + mid = (edge[i] + edge[i + 1]) / 2; +- if (selection->x1 < mid || selection->x2 < mid) +- if (i < begin) +- begin = i; +- if (mid < selection->x1 || mid < selection->x2) +- end = i + 1; ++ if (XBetweenAB (mid, s1, s2)) ++ { ++ if (i < begin) ++ begin = i; ++ ++ end = i + 1; ++ } + } + + /* Skip empty selection. */ +@@ -4615,30 +4694,41 @@ void TextLine::visitSelection(TextSelectionVisitor *visitor, + TextWord *p, *begin, *end, *current; + int i, edge_begin, edge_end; + PDFRectangle child_selection; ++ double s1, s2, p_min, p_max; ++ ++ if (rot == 0 || rot == 2) { ++ s1 = selection->x1; ++ s2 = selection->x2; ++ } else { ++ s1 = selection->y1; ++ s2 = selection->y2; ++ } + + begin = nullptr; + end = nullptr; + current = nullptr; + for (p = words; p != nullptr; p = p->next) { ++ if (rot == 0 || rot == 2) { ++ p_min = p->xMin; ++ p_max = p->xMax; ++ } else { ++ p_min = p->yMin; ++ p_max = p->yMax; ++ } ++ + if (blk->page->primaryLR) { +- if ((selection->x1 < p->xMax) || +- (selection->x2 < p->xMax)) +- if (begin == nullptr) +- begin = p; ++ if (((s1 < p_max) || (s2 < p_max)) && begin == nullptr) ++ begin = p; + +- if (((selection->x1 > p->xMin) || +- (selection->x2 > p->xMin)) && (begin != nullptr)) { ++ if (((s1 > p_min) || (s2 > p_min)) && begin != nullptr) { + end = p->next; + current = p; + } + } else { +- if ((selection->x1 > p->xMin) || +- (selection->x2 > p->xMin)) +- if (begin == nullptr) +- begin = p; ++ if (((s1 > p_min) || (s2 > p_min)) && begin == nullptr) ++ begin = p; + +- if (((selection->x1 < p->xMax) || +- (selection->x2 < p->xMax)) && (begin != nullptr)) { ++ if (((s1 < p_max) || (s2 < p_max)) && begin != nullptr) { + end = p->next; + current = p; + } +@@ -4650,23 +4740,42 @@ void TextLine::visitSelection(TextSelectionVisitor *visitor, + + child_selection = *selection; + if (style == selectionStyleWord) { +- child_selection.x1 = begin ? begin->xMin : xMin; +- if (end && end->xMax != -1) { +- child_selection.x2 = current->xMax; ++ if (rot == 0 || rot == 2) { ++ child_selection.x1 = begin ? begin->xMin : xMin; ++ if (end && end->xMax != -1) { ++ child_selection.x2 = current->xMax; ++ } else { ++ child_selection.x2 = xMax; ++ } + } else { +- child_selection.x2 = xMax; ++ child_selection.y1 = begin ? begin->yMin : yMin; ++ if (end && end->yMax != -1) { ++ child_selection.y2 = current->yMax; ++ } else { ++ child_selection.y2 = yMax; ++ } + } + } + ++ if (rot == 0 || rot == 2) { ++ s1 = child_selection.x1; ++ s2 = child_selection.x2; ++ } else { ++ s1 = child_selection.y1; ++ s2 = child_selection.y2; ++ } ++ + edge_begin = len; + edge_end = 0; + for (i = 0; i < len; i++) { + double mid = (edge[i] + edge[i + 1]) / 2; +- if (child_selection.x1 < mid || child_selection.x2 < mid) +- if (i < edge_begin) +- edge_begin = i; +- if (mid < child_selection.x2 || mid < child_selection.x1) +- edge_end = i + 1; ++ if (XBetweenAB (mid, s1, s2)) ++ { ++ if (i < edge_begin) ++ edge_begin = i; ++ ++ edge_end = i + 1; ++ } + } + + /* Skip empty selection. */ +-- +1.8.4.2 + diff --git a/SOURCES/poppler-0.62.0-python3.patch b/SOURCES/poppler-0.62.0-python3.patch new file mode 100644 index 0000000..6234822 --- /dev/null +++ b/SOURCES/poppler-0.62.0-python3.patch @@ -0,0 +1,8 @@ +--- poppler-0.62.0/make-glib-api-docs ++++ poppler-0.62.0/make-glib-api-docs +@@ -1,4 +1,4 @@ +-#!/usr/bin/env python ++#!/usr/bin/env python3 + # + # Copyright (C) 2017 Carlos Garcia Campos + # diff --git a/SOURCES/poppler-0.66.0-JPXStream-length.patch b/SOURCES/poppler-0.66.0-JPXStream-length.patch new file mode 100644 index 0000000..ecd52b8 --- /dev/null +++ b/SOURCES/poppler-0.66.0-JPXStream-length.patch @@ -0,0 +1,26 @@ +From 68ef84e5968a4249c2162b839ca6d7975048a557 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Mon, 15 Jul 2019 23:24:22 +0200 +Subject: [PATCH] JPXStream::init: ignore dict Length if clearly broken + +Fixes issue #805 +--- + poppler/JPEG2000Stream.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/poppler/JPEG2000Stream.cc b/poppler/JPEG2000Stream.cc +index 0eea3a2d..8e6902f4 100644 +--- a/poppler/JPEG2000Stream.cc ++++ b/poppler/JPEG2000Stream.cc +@@ -219,7 +219,7 @@ void JPXStream::init() + } + + int bufSize = BUFFER_INITIAL_SIZE; +- if (oLen.isInt()) bufSize = oLen.getInt(); ++ if (oLen.isInt() && oLen.getInt() > 0) bufSize = oLen.getInt(); + + GBool indexed = gFalse; + if (cspace.isArray() && cspace.arrayGetLength() > 0) { +-- +2.21.0 + diff --git a/SOURCES/poppler-0.66.0-PSOutputDev-rgb.patch b/SOURCES/poppler-0.66.0-PSOutputDev-rgb.patch new file mode 100644 index 0000000..70f173a --- /dev/null +++ b/SOURCES/poppler-0.66.0-PSOutputDev-rgb.patch @@ -0,0 +1,372 @@ +From 64aa150a92ccb082db6a3383fa734a6ac91cf1bf Mon Sep 17 00:00:00 2001 +From: Marek Kasik +Date: Tue, 30 Apr 2019 18:47:44 +0200 +Subject: [PATCH] PSOutputDev: Don't read outside of image buffer + +Check whether input image is RGB or BGR to not treat +it as CMYK in those cases in PSOutputDev::checkPageSlice(). + +Fixes #751 +--- + poppler/PSOutputDev.cc | 248 ++++++++++++++++++++++++++++++++--------- + 1 file changed, 196 insertions(+), 52 deletions(-) + +diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc +index 0d201835..155a8cbe 100644 +--- a/poppler/PSOutputDev.cc ++++ b/poppler/PSOutputDev.cc +@@ -3385,13 +3385,21 @@ GBool PSOutputDev::checkPageSlice(Page * + } + break; + case psLevel1Sep: ++ GfxColor inputColor; ++ GfxCMYK cmyk; ++ unsigned char cmykColor[4]; ++ GfxDeviceRGBColorSpace *rgbCS; ++ SplashColorMode colorMode; ++ ++ colorMode = bitmap->getMode(); ++ + p = bitmap->getDataPtr(); + // Check for an all gray image + if (getOptimizeColorSpace()) { + isGray = gTrue; + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { +- if (p[4*x] != p[4*x + 1] || p[4*x] != p[4*x + 2]) { ++ if (p[numComps*x] != p[numComps*x + 1] || p[numComps*x] != p[numComps*x + 2]) { + isGray = gFalse; + y = h; + break; +@@ -3411,7 +3419,9 @@ GBool PSOutputDev::checkPageSlice(Page * + col[0] = col[1] = col[2] = col[3] = 0; + if (isGray) { + int g; +- if ((psProcessBlack & processColors) == 0) { ++ if ((psProcessBlack & processColors) == 0 && ++ colorMode != splashModeRGB8 && ++ colorMode != splashModeBGR8) { + // Check if the image uses black + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { +@@ -3425,59 +3435,23 @@ GBool PSOutputDev::checkPageSlice(Page * + } + p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize(); + } +- for (y = 0; y < h; ++y) { +- if (useBinary) { +- // Binary gray image +- for (x = 0; x < w; ++x) { +- g = p[4*x] + p[4*x + 3]; +- g = 255 - g; +- if (g < 0) g = 0; +- hexBuf[i++] = (Guchar) g; +- if (i >= 64) { +- writePSBuf(hexBuf, i); +- i = 0; +- } +- } +- } else { +- // Hex gray image +- for (x = 0; x < w; ++x) { +- g = p[4*x] + p[4*x + 3]; +- g = 255 - g; +- if (g < 0) g = 0; +- digit = g / 16; +- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); +- digit = g % 16; +- hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); +- if (i >= 64) { +- hexBuf[i++] = '\n'; +- writePSBuf(hexBuf, i); +- i = 0; +- } +- } +- } +- p -= bitmap->getRowSize(); +- } +- } else if (((psProcessCyan | psProcessMagenta | psProcessYellow | psProcessBlack) & ~processColors) != 0) { +- // Color image, need to check color flags for each dot +- for (y = 0; y < h; ++y) { +- for (comp = 0; comp < 4; ++comp) { ++ if (colorMode == splashModeRGB8 || colorMode != splashModeBGR8) { ++ for (y = 0; y < h; ++y) { + if (useBinary) { +- // Binary color image ++ // Binary gray image + for (x = 0; x < w; ++x) { +- col[comp] |= p[4*x + comp]; +- hexBuf[i++] = p[4*x + comp]; ++ hexBuf[i++] = (Guchar) p[3*x]; + if (i >= 64) { + writePSBuf(hexBuf, i); + i = 0; + } + } + } else { +- // Gray color image ++ // Hex gray image + for (x = 0; x < w; ++x) { +- col[comp] |= p[4*x + comp]; +- digit = p[4*x + comp] / 16; ++ digit = p[3*x] / 16; + hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); +- digit = p[4*x + comp] % 16; ++ digit = p[3*x] % 16; + hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); + if (i >= 64) { + hexBuf[i++] = '\n'; +@@ -3485,29 +3459,31 @@ GBool PSOutputDev::checkPageSlice(Page * + i = 0; + } + } +- } ++ } + } +- p -= bitmap->getRowSize(); +- } +- } else { +- // Color image, do not need to check color flags +- for (y = 0; y < h; ++y) { +- for (comp = 0; comp < 4; ++comp) { ++ } else { ++ for (y = 0; y < h; ++y) { + if (useBinary) { +- // Binary color image ++ // Binary gray image + for (x = 0; x < w; ++x) { +- hexBuf[i++] = p[4*x + comp]; ++ g = p[4*x] + p[4*x + 3]; ++ g = 255 - g; ++ if (g < 0) g = 0; ++ hexBuf[i++] = (Guchar) g; + if (i >= 64) { + writePSBuf(hexBuf, i); + i = 0; + } + } + } else { +- // Hex color image ++ // Hex gray image + for (x = 0; x < w; ++x) { +- digit = p[4*x + comp] / 16; ++ g = p[4*x] + p[4*x + 3]; ++ g = 255 - g; ++ if (g < 0) g = 0; ++ digit = g / 16; + hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); +- digit = p[4*x + comp] % 16; ++ digit = g % 16; + hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); + if (i >= 64) { + hexBuf[i++] = '\n'; +@@ -3515,9 +3491,207 @@ GBool PSOutputDev::checkPageSlice(Page * + i = 0; + } + } +- } ++ } + } +- p -= bitmap->getRowSize(); ++ } ++ p -= bitmap->getRowSize(); ++ } else if (((psProcessCyan | psProcessMagenta | psProcessYellow | psProcessBlack) & ~processColors) != 0) { ++ // Color image, need to check color flags for each dot ++ switch (colorMode) { ++ case splashModeRGB8: ++ case splashModeBGR8: ++ rgbCS = new GfxDeviceRGBColorSpace(); ++ for (y = 0; y < h; ++y) { ++ for (comp = 0; comp < 4; ++comp) { ++ if (useBinary) { ++ // Binary color image ++ for (x = 0; x < w; ++x) { ++ if (likely(colorMode == splashModeRGB8)) { ++ inputColor.c[0] = byteToCol(p[3*x + 0]); ++ inputColor.c[1] = byteToCol(p[3*x + 1]); ++ inputColor.c[2] = byteToCol(p[3*x + 2]); ++ } else { ++ inputColor.c[0] = byteToCol(p[3*x + 2]); ++ inputColor.c[1] = byteToCol(p[3*x + 1]); ++ inputColor.c[2] = byteToCol(p[3*x + 0]); ++ } ++ rgbCS->getCMYK(&inputColor, &cmyk); ++ cmykColor[0] = colToByte(cmyk.c); ++ cmykColor[1] = colToByte(cmyk.m); ++ cmykColor[2] = colToByte(cmyk.y); ++ cmykColor[3] = colToByte(cmyk.k); ++ ++ col[comp] |= cmykColor[comp]; ++ hexBuf[i++] = cmykColor[comp]; ++ if (i >= 64) { ++ writePSBuf(hexBuf, i); ++ i = 0; ++ } ++ } ++ } else { ++ // Gray color image ++ for (x = 0; x < w; ++x) { ++ if (likely(colorMode == splashModeRGB8)) { ++ inputColor.c[0] = byteToCol(p[3*x + 0]); ++ inputColor.c[1] = byteToCol(p[3*x + 1]); ++ inputColor.c[2] = byteToCol(p[3*x + 2]); ++ } else { ++ inputColor.c[0] = byteToCol(p[3*x + 2]); ++ inputColor.c[1] = byteToCol(p[3*x + 1]); ++ inputColor.c[2] = byteToCol(p[3*x + 0]); ++ } ++ rgbCS->getCMYK(&inputColor, &cmyk); ++ cmykColor[0] = colToByte(cmyk.c); ++ cmykColor[1] = colToByte(cmyk.m); ++ cmykColor[2] = colToByte(cmyk.y); ++ cmykColor[3] = colToByte(cmyk.k); ++ ++ col[comp] |= cmykColor[comp]; ++ digit = cmykColor[comp] / 16; ++ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); ++ digit = cmykColor[comp] % 16; ++ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); ++ if (i >= 64) { ++ hexBuf[i++] = '\n'; ++ writePSBuf(hexBuf, i); ++ i = 0; ++ } ++ } ++ } ++ } ++ p -= bitmap->getRowSize(); ++ } ++ delete rgbCS; ++ break; ++ default: ++ for (y = 0; y < h; ++y) { ++ for (comp = 0; comp < 4; ++comp) { ++ if (useBinary) { ++ // Binary color image ++ for (x = 0; x < w; ++x) { ++ col[comp] |= p[4*x + comp]; ++ hexBuf[i++] = p[4*x + comp]; ++ if (i >= 64) { ++ writePSBuf(hexBuf, i); ++ i = 0; ++ } ++ } ++ } else { ++ // Gray color image ++ for (x = 0; x < w; ++x) { ++ col[comp] |= p[4*x + comp]; ++ digit = p[4*x + comp] / 16; ++ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); ++ digit = p[4*x + comp] % 16; ++ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); ++ if (i >= 64) { ++ hexBuf[i++] = '\n'; ++ writePSBuf(hexBuf, i); ++ i = 0; ++ } ++ } ++ } ++ } ++ p -= bitmap->getRowSize(); ++ } ++ break; ++ } ++ } else { ++ // Color image, do not need to check color flags ++ switch (colorMode) { ++ case splashModeRGB8: ++ case splashModeBGR8: ++ rgbCS = new GfxDeviceRGBColorSpace(); ++ for (y = 0; y < h; ++y) { ++ for (comp = 0; comp < 4; ++comp) { ++ if (useBinary) { ++ // Binary color image ++ for (x = 0; x < w; ++x) { ++ if (likely(colorMode == splashModeRGB8)) { ++ inputColor.c[0] = byteToCol(p[3*x + 0]); ++ inputColor.c[1] = byteToCol(p[3*x + 1]); ++ inputColor.c[2] = byteToCol(p[3*x + 2]); ++ } else { ++ inputColor.c[0] = byteToCol(p[3*x + 2]); ++ inputColor.c[1] = byteToCol(p[3*x + 1]); ++ inputColor.c[2] = byteToCol(p[3*x + 0]); ++ } ++ rgbCS->getCMYK(&inputColor, &cmyk); ++ cmykColor[0] = colToByte(cmyk.c); ++ cmykColor[1] = colToByte(cmyk.m); ++ cmykColor[2] = colToByte(cmyk.y); ++ cmykColor[3] = colToByte(cmyk.k); ++ ++ hexBuf[i++] = cmykColor[comp]; ++ if (i >= 64) { ++ writePSBuf(hexBuf, i); ++ i = 0; ++ } ++ } ++ } else { ++ // Hex color image ++ for (x = 0; x < w; ++x) { ++ if (likely(colorMode == splashModeRGB8)) { ++ inputColor.c[0] = byteToCol(p[3*x + 0]); ++ inputColor.c[1] = byteToCol(p[3*x + 1]); ++ inputColor.c[2] = byteToCol(p[3*x + 2]); ++ } else { ++ inputColor.c[0] = byteToCol(p[3*x + 2]); ++ inputColor.c[1] = byteToCol(p[3*x + 1]); ++ inputColor.c[2] = byteToCol(p[3*x + 0]); ++ } ++ rgbCS->getCMYK(&inputColor, &cmyk); ++ cmykColor[0] = colToByte(cmyk.c); ++ cmykColor[1] = colToByte(cmyk.m); ++ cmykColor[2] = colToByte(cmyk.y); ++ cmykColor[3] = colToByte(cmyk.k); ++ ++ digit = cmykColor[comp] / 16; ++ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); ++ digit = cmykColor[comp] % 16; ++ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); ++ if (i >= 64) { ++ hexBuf[i++] = '\n'; ++ writePSBuf(hexBuf, i); ++ i = 0; ++ } ++ } ++ } ++ } ++ p -= bitmap->getRowSize(); ++ } ++ delete rgbCS; ++ break; ++ default: ++ for (y = 0; y < h; ++y) { ++ for (comp = 0; comp < 4; ++comp) { ++ if (useBinary) { ++ // Binary color image ++ for (x = 0; x < w; ++x) { ++ hexBuf[i++] = p[4*x + comp]; ++ if (i >= 64) { ++ writePSBuf(hexBuf, i); ++ i = 0; ++ } ++ } ++ } else { ++ // Hex color image ++ for (x = 0; x < w; ++x) { ++ digit = p[4*x + comp] / 16; ++ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); ++ digit = p[4*x + comp] % 16; ++ hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0'); ++ if (i >= 64) { ++ hexBuf[i++] = '\n'; ++ writePSBuf(hexBuf, i); ++ i = 0; ++ } ++ } ++ } ++ } ++ p -= bitmap->getRowSize(); ++ } ++ break; + } + } + if (i != 0) { diff --git a/SOURCES/poppler-0.66.0-check-catalog-is-dict.patch b/SOURCES/poppler-0.66.0-check-catalog-is-dict.patch new file mode 100644 index 0000000..73fa712 --- /dev/null +++ b/SOURCES/poppler-0.66.0-check-catalog-is-dict.patch @@ -0,0 +1,29 @@ +--- a/utils/pdfunite.cc ++++ b/utils/pdfunite.cc +@@ -165,7 +165,9 @@ int main (int argc, char *argv[]) + for (i = 1; i < argc - 1; i++) { + GooString *gfileName = new GooString(argv[i]); + PDFDoc *doc = new PDFDoc(gfileName, nullptr, nullptr, nullptr); +- if (doc->isOk() && !doc->isEncrypted()) { ++ if (doc->isOk() && !doc->isEncrypted() && ++ (doc->getCatalog()->getPageRef(1) || gTrue) && ++ doc->getXRef()->getCatalog().isDict()) { + docs.push_back(doc); + if (doc->getPDFMajorVersion() > majorVersion) { + majorVersion = doc->getPDFMajorVersion(); +@@ -176,8 +177,13 @@ int main (int argc, char *argv[]) + } + } + } else if (doc->isOk()) { +- error(errUnimplemented, -1, "Could not merge encrypted files ('{0:s}')", argv[i]); +- return -1; ++ if (doc->isEncrypted()) { ++ error(errUnimplemented, -1, "Could not merge encrypted files ('{0:s}')", argv[i]); ++ return -1; ++ } else if (!doc->getXRef()->getCatalog().isDict()) { ++ error(errSyntaxError, -1, "XRef's Catalog is not a dictionary ('{0:s}')", argv[i]); ++ return -1; ++ } + } else { + error(errSyntaxError, -1, "Could not merge damaged documents ('{0:s}')", argv[i]); + return -1; diff --git a/SOURCES/poppler-0.66.0-coverage-values.patch b/SOURCES/poppler-0.66.0-coverage-values.patch new file mode 100644 index 0000000..74cb731 --- /dev/null +++ b/SOURCES/poppler-0.66.0-coverage-values.patch @@ -0,0 +1,35 @@ +From d716e636231c8d636bf2139896d817b66fe6d510 Mon Sep 17 00:00:00 2001 +From: Marek Kasik +Date: Thu, 21 Mar 2019 13:15:37 +0100 +Subject: [PATCH 1/2] cairo: Compute correct coverage values for box filter + +Use double precision for computation of coverage +of the left most pixel in the box filter. + +Issue #736 +--- + poppler/CairoRescaleBox.cc | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/poppler/CairoRescaleBox.cc b/poppler/CairoRescaleBox.cc +index b8371a5b..d7615010 100644 +--- a/poppler/CairoRescaleBox.cc ++++ b/poppler/CairoRescaleBox.cc +@@ -226,10 +227,10 @@ static int compute_coverage (int coverage[], int src_length, int dest_length) + /* I have a proof of this, which this margin is too narrow to contain */ + for (i=0; igetWidget (fieldNum); +- if (field) +- return _poppler_form_field_new (document, field); ++ if (field) { ++ formField = _poppler_form_field_new (document, field); ++ delete widgets; ++ ++ return formField; ++ } ++ ++ delete widgets; + + return nullptr; + } +--- poppler/poppler/CairoOutputDev.cc ++++ poppler/poppler/CairoOutputDev.cc +@@ -3010,8 +3010,10 @@ void CairoOutputDev::setMimeData(GfxStat + + // colorspace in stream dict may be different from colorspace in jpx + // data +- if (strKind == strJPX && colorSpace) ++ if (strKind == strJPX && colorSpace) { ++ delete colorSpace; + return; ++ } + + // only embed mime data for gray, rgb, and cmyk colorspaces. + if (colorSpace) { +--- poppler/poppler/Link.cc ++++ poppler/poppler/Link.cc +@@ -193,6 +193,7 @@ LinkAction *LinkAction::parseAction(cons + const Ref ref = obj3Ref.getRef(); + if (!seenNextActions->insert(ref.num).second) { + error(errSyntaxWarning, -1, "parseAction: Circular next actions detected in array."); ++ delete actionList; + return action; + } + } +--- poppler/poppler/SplashOutputDev.cc ++++ poppler/poppler/SplashOutputDev.cc +@@ -2207,6 +2207,8 @@ reload: + error(errSyntaxError, -1, "Couldn't create a font for '{0:s}'", + gfxFont->getName() ? gfxFont->getName()->getCString() + : "(unnamed)"); ++ if (fontsrc && fontsrc->isFile) ++ fontsrc->unref(); + goto err2; + } + codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n); +@@ -2225,6 +2227,8 @@ reload: + break; + default: + // this shouldn't happen ++ if (fontsrc && fontsrc->isFile) ++ fontsrc->unref(); + goto err2; + } + fontFile->doAdjustMatrix = doAdjustFontMatrix; +--- poppler/poppler/TextOutputDev.cc ++++ poppler/poppler/TextOutputDev.cc +@@ -1526,7 +1526,6 @@ TextBlock::~TextBlock() { + } + + void TextBlock::addWord(TextWord *word) { +- pool->addWord(word); + if (xMin > xMax) { + xMin = word->xMin; + xMax = word->xMax; +@@ -1546,6 +1545,7 @@ void TextBlock::addWord(TextWord *word) + yMax = word->yMax; + } + } ++ pool->addWord(word); + } + + void TextBlock::coalesce(UnicodeMap *uMap, double fixedPitch) { +@@ -2999,11 +2999,13 @@ void TextPage::coalesce(GBool physLayout + word0 = pool->getPool(startBaseIdx); + pool->setPool(startBaseIdx, word0->next); + word0->next = nullptr; +- blk = new TextBlock(this, rot); +- blk->addWord(word0); + + fontSize = word0->fontSize; + minBase = maxBase = word0->base; ++ ++ blk = new TextBlock(this, rot); ++ blk->addWord(word0); ++ + colSpace1 = minColSpacing1 * fontSize; + colSpace2 = minColSpacing2 * fontSize; + lineSpace = maxLineSpacingDelta * fontSize; +@@ -3037,9 +3039,9 @@ void TextPage::coalesce(GBool physLayout + } + word1 = word1->next; + word2->next = nullptr; ++ newMinBase = word2->base; + blk->addWord(word2); + found = gTrue; +- newMinBase = word2->base; + } else { + word0 = word1; + word1 = word1->next; +@@ -3072,9 +3074,9 @@ void TextPage::coalesce(GBool physLayout + } + word1 = word1->next; + word2->next = nullptr; ++ newMaxBase = word2->base; + blk->addWord(word2); + found = gTrue; +- newMaxBase = word2->base; + } else { + word0 = word1; + word1 = word1->next; +@@ -3171,12 +3173,12 @@ void TextPage::coalesce(GBool physLayout + } + word1 = word1->next; + word2->next = nullptr; +- blk->addWord(word2); + if (word2->base < minBase) { + minBase = word2->base; + } else if (word2->base > maxBase) { + maxBase = word2->base; + } ++ blk->addWord(word2); + found = gTrue; + break; + } else { +@@ -3235,12 +3237,12 @@ void TextPage::coalesce(GBool physLayout + } + word1 = word1->next; + word2->next = nullptr; +- blk->addWord(word2); + if (word2->base < minBase) { + minBase = word2->base; + } else if (word2->base > maxBase) { + maxBase = word2->base; + } ++ blk->addWord(word2); + found = gTrue; + break; + } else { +@@ -4509,7 +4511,7 @@ GooList **TextSelectionDumper::takeWordL + class TextSelectionSizer : public TextSelectionVisitor { + public: + TextSelectionSizer(TextPage *page, double scale); +- ~TextSelectionSizer() { } ++ ~TextSelectionSizer(); + + void visitBlock (TextBlock *block, + TextLine *begin, +@@ -4526,7 +4526,7 @@ public: + void visitWord (TextWord *word, int begin, int end, + PDFRectangle *selection) override { }; + +- GooList *getRegion () { return list; } ++ GooList *getRegion (); + + private: + GooList *list; +@@ -4538,6 +4540,11 @@ TextSelectionSizer::TextSelectionSizer(T + list = new GooList(); + } + ++TextSelectionSizer::~TextSelectionSizer() ++{ ++ deleteGooList(list, PDFRectangle); ++} ++ + void TextSelectionSizer::visitLine (TextLine *line, + TextWord *begin, + TextWord *end, +@@ -4594,6 +4594,21 @@ void TextSelectionSizer::visitLine (Text + list->append (rect); + } + ++GooList *TextSelectionSizer::getRegion () { ++ GooList *recList; ++ int i; ++ ++ recList = new GooList(); ++ ++ for (i = 0; i < list->getLength(); i++) { ++ PDFRectangle *selection_rect = (PDFRectangle *) list->get(i); ++ ++ recList->append (new PDFRectangle(selection_rect->x1, selection_rect->y1, selection_rect->x2, selection_rect->y2)); ++ } ++ ++ return recList; ++} ++ + + class TextSelectionPainter : public TextSelectionVisitor { + public: +--- poppler/poppler/XRef.cc ++++ poppler/poppler/XRef.cc +@@ -456,6 +456,7 @@ int XRef::reserve(int newSize) + + void *p = greallocn_checkoverflow(entries, realNewSize, sizeof(XRefEntry)); + if (p == nullptr) { ++ entries = nullptr; + return 0; + } + +@@ -877,7 +878,6 @@ GBool XRef::constructXRef(GBool *wasReco + int offset = 0; + + resize(0); // free entries properly +- gfree(entries); + capacity = 0; + size = 0; + entries = nullptr; +--- poppler/qt5/src/ArthurOutputDev.cc ++++ poppler/qt5/src/ArthurOutputDev.cc +@@ -703,7 +703,11 @@ void ArthurOutputDev::updateFont(GfxStat + else + ff = FoFiTrueType::make(tmpBuf, tmpBufLen); + if (! ff) ++ { ++ if (fontsrc && fontsrc->isFile) ++ fontsrc->unref(); + goto err2; ++ } + codeToGID = ((GfxCIDFont *)gfxFont)->getCodeToGIDMap(ff, &n); + delete ff; + } +@@ -719,6 +723,8 @@ void ArthurOutputDev::updateFont(GfxStat + break; + default: + // this shouldn't happen ++ if (fontsrc && fontsrc->isFile) ++ fontsrc->unref(); + goto err2; + } + } +@@ -738,6 +744,8 @@ void ArthurOutputDev::updateFont(GfxStat + return; + + err2: ++ if (fontsrc && !fontsrc->isFile) ++ fontsrc->unref(); + delete id; + #endif + } +--- poppler/qt5/src/poppler-page.cc ++++ poppler/qt5/src/poppler-page.cc +@@ -782,6 +782,7 @@ QList Page::textList(Rotation + + if (!word_list || (shouldAbortExtractionCallback && shouldAbortExtractionCallback(closure))) { + delete output_dev; ++ delete word_list; + return output_list; + } + +--- poppler/test/pdf-inspector.cc ++++ poppler/test/pdf-inspector.cc +@@ -46,6 +46,7 @@ class PdfInspector { + public: + + PdfInspector(void); ++ ~PdfInspector(void); + + void set_file_name (const char *file_name); + void load (const char *file_name); +@@ -136,6 +137,11 @@ PdfInspector::PdfInspector(void) + // set up initial widgets + load (nullptr); + } ++ ++PdfInspector::~PdfInspector(void) ++{ ++ delete output; ++} + + void + PdfInspector::set_file_name(const char *file_name) +--- poppler/test/perf-test.cc ++++ poppler/test/perf-test.cc +@@ -1053,6 +1053,7 @@ static void ParseCommandLine(int argc, c + ++i; + if (i == argc) + PrintUsageAndExit(argc, argv); ++ free(gOutFileName); + gOutFileName = str_dup(argv[i]); + } else if (str_ieq(arg, PREVIEW_ARG)) { + gfPreview = true; +--- poppler/utils/HtmlOutputDev.cc ++++ poppler/utils/HtmlOutputDev.cc +@@ -920,10 +920,11 @@ void HtmlPage::dumpComplex(FILE *file, i + + fputs("\n", pageFile); + +- if( !noframes ) +- { ++ if( !noframes ){ + fputs("\n\n",pageFile); + fclose(pageFile); ++ } else if (pageFile != nullptr && pageFile != file){ ++ fclose(pageFile); + } + } + +@@ -1376,6 +1377,7 @@ void HtmlOutputDev::drawPngImage(GfxStat + // TODO can we calculate the resolution of the image? + if (!writer->init(f1, width, height, 72, 72)) { + error(errInternal, -1, "Can't init PNG for image '{0:t}'", fName); ++ delete fName; + delete writer; + fclose(f1); + return; +@@ -1417,6 +1419,7 @@ void HtmlOutputDev::drawPngImage(GfxStat + + if (!writer->writeRow(row_pointer)) { + error(errIO, -1, "Failed to write into PNG '{0:t}'", fName); ++ delete fName; + delete writer; + delete imgStr; + fclose(f1); +@@ -1455,6 +1458,7 @@ void HtmlOutputDev::drawPngImage(GfxStat + if (!writer->writeRow( &png_row )) + { + error(errIO, -1, "Failed to write into PNG '{0:t}'", fName); ++ delete fName; + delete writer; + fclose(f1); + gfree(png_row); +@@ -1472,6 +1476,8 @@ void HtmlOutputDev::drawPngImage(GfxStat + fclose(f1); + + pages->addImage(fName, state); ++ ++ delete fName; + #else + return; + #endif +@@ -1617,6 +1623,7 @@ GooString* HtmlOutputDev::getLinkDest(An + } + else + { ++ delete file; + return new GooString(); + } + } +--- poppler/utils/pdftotext.cc ++++ poppler/utils/pdftotext.cc +@@ -356,6 +356,7 @@ int main(int argc, char *argv[]) { + fputs("
\n", f);
+       if (f != stdout) {
+ 	fclose(f);
++	f = nullptr;
+       }
+     }
+   }
+@@ -372,8 +373,9 @@ int main(int argc, char *argv[]) {
+         printWordBBox(f, doc, textOut, firstPage, lastPage);
+       }
+     }
+-    if (f != stdout) {
++    if (f != stdout && f != nullptr) {
+       fclose(f);
++      f = nullptr;
+     }
+   } else {
+     textOut = new TextOutputDev(textFileName->getCString(),
+@@ -413,7 +415,7 @@ int main(int argc, char *argv[]) {
+     if (!bbox) fputs("
\n", f); + fputs("\n", f); + fputs("\n", f); +- if (f != stdout) { ++ if (f != stdout && f != nullptr) { + fclose(f); + } + } diff --git a/SOURCES/poppler-0.66.0-cycles-in-pdf-parsing.patch b/SOURCES/poppler-0.66.0-cycles-in-pdf-parsing.patch new file mode 100644 index 0000000..698923a --- /dev/null +++ b/SOURCES/poppler-0.66.0-cycles-in-pdf-parsing.patch @@ -0,0 +1,61 @@ +From 3d35d209c19c1d3b09b794a0c863ba5de44a9c0a Mon Sep 17 00:00:00 2001 +From: Marek Kasik +Date: Mon, 29 Oct 2018 17:44:47 +0100 +Subject: [PATCH] Avoid cycles in PDF parsing + +Mark objects being processed in Parser::makeStream() as being processed +and check the mark when entering this method to avoid processing +of the same object recursively. +--- + poppler/Parser.cc | 15 +++++++++++++++ + poppler/XRef.h | 1 + + 2 files changed, 16 insertions(+) + +diff --git a/poppler/Parser.cc b/poppler/Parser.cc +index bd4845ab..8f48efbe 100644 +--- a/poppler/Parser.cc ++++ b/poppler/Parser.cc +@@ -197,6 +197,18 @@ Stream *Parser::makeStream(Object &&dict, Guchar *fileKey, + Stream *str; + Goffset length; + Goffset pos, endPos; ++ XRefEntry *entry = nullptr; ++ ++ if (xref && (entry = xref->getEntry(objNum, false))) { ++ if (!entry->getFlag(XRefEntry::Parsing) || ++ (objNum == 0 && objGen == 0)) { ++ entry->setFlag(XRefEntry::Parsing, true); ++ } else { ++ error(errSyntaxError, getPos(), ++ "Object '{0:d} {1:d} obj' is being already parsed", objNum, objGen); ++ return nullptr; ++ } ++ } + + // get stream start position + lexer->skipToNextLine(); +@@ -278,6 +290,9 @@ Stream *Parser::makeStream(Object &&dict, Guchar *fileKey, + // get filters + str = str->addFilters(str->getDict(), recursion); + ++ if (entry) ++ entry->setFlag(XRefEntry::Parsing, false); ++ + return str; + } + +diff --git a/poppler/XRef.h b/poppler/XRef.h +index 11ee5e03..2eb2f9fd 100644 +--- a/poppler/XRef.h ++++ b/poppler/XRef.h +@@ -65,6 +65,7 @@ struct XRefEntry { + enum Flag { + // Regular flags + Updated, // Entry was modified ++ Parsing, // Entry is currently being parsed + + // Special flags -- available only after xref->scanSpecialFlags() is run + Unencrypted, // Entry is stored in unencrypted form (meaningless in unencrypted documents) +-- +2.19.1 + diff --git a/SOURCES/poppler-0.66.0-display-profile.patch b/SOURCES/poppler-0.66.0-display-profile.patch new file mode 100644 index 0000000..a9f5c58 --- /dev/null +++ b/SOURCES/poppler-0.66.0-display-profile.patch @@ -0,0 +1,63 @@ +From e07c8b4784234383cb5ddcf1133ea91a772506e2 Mon Sep 17 00:00:00 2001 +From: Adam Reichold +Date: Tue, 1 Jan 2019 10:54:40 +0100 +Subject: [PATCH] Avoid global display profile state becoming an uncontrolled + memory leak by enforcing single initialization. Closes #654 + +--- + poppler/GfxState.cc | 9 +++++++++ + qt5/src/poppler-qt5.h | 4 ++++ + 2 files changed, 13 insertions(+) + +diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc +index 87b7ce03..4e3ccbfd 100644 +--- a/poppler/GfxState.cc ++++ b/poppler/GfxState.cc +@@ -226,6 +226,10 @@ static unsigned int getCMSNChannels(cmsColorSpaceSignature cs); + static cmsHPROFILE loadColorProfile(const char *fileName); + + void GfxColorSpace::setDisplayProfile(void *displayProfileA) { ++ if (displayProfile != nullptr) { ++ error(errInternal, -1, "The display color profile can only be set once before any rendering is done."); ++ return; ++ } + displayProfile = displayProfileA; + if (displayProfile != nullptr) { + cmsHTRANSFORM transform; +@@ -249,6 +253,11 @@ void GfxColorSpace::setDisplayProfile(void *displayProfileA) { + } + + void GfxColorSpace::setDisplayProfileName(GooString *name) { ++ if (displayProfile != nullptr) { ++ error(errInternal, -1, "The display color profile can only be set before any rendering is done."); ++ return; ++ } ++ delete displayProfileName; + displayProfileName = name->copy(); + } + +diff --git a/qt5/src/poppler-qt5.h b/qt5/src/poppler-qt5.h +index 4f06c47e..ddac7dfb 100644 +--- a/qt5/src/poppler-qt5.h ++++ b/qt5/src/poppler-qt5.h +@@ -1102,6 +1102,8 @@ delete it; + + \param outputProfileA is a \c cmsHPROFILE of the LCMS library. + ++ \note This should be called before any rendering happens and only once during the lifetime of the current process. ++ + \since 0.12 + */ + void setColorDisplayProfile(void *outputProfileA); +@@ -1110,6 +1112,8 @@ delete it; + + \param name is the name of the display profile to set. + ++ \note This should be called before any rendering happens. ++ + \since 0.12 + */ + void setColorDisplayProfileName(const QString &name); +-- +2.20.1 + diff --git a/SOURCES/poppler-0.66.0-dummy-xref-entry.patch b/SOURCES/poppler-0.66.0-dummy-xref-entry.patch new file mode 100644 index 0000000..bc1f5a1 --- /dev/null +++ b/SOURCES/poppler-0.66.0-dummy-xref-entry.patch @@ -0,0 +1,63 @@ +From 39a251b1b3a3343400a08e2f03c5518a26624626 Mon Sep 17 00:00:00 2001 +From: Adam Reichold +Date: Mon, 24 Dec 2018 15:40:38 +0100 +Subject: [PATCH] Do not try to parse into unallocated XRef entry and return + pointer to dummy entry instead. Closes #692 and oss-fuzz/12330 + +--- + poppler/XRef.cc | 27 +++++++++++++++++++++------ + 1 file changed, 21 insertions(+), 6 deletions(-) + +diff --git a/poppler/XRef.cc b/poppler/XRef.cc +index 0ec66944..d042d1f4 100644 +--- a/poppler/XRef.cc ++++ b/poppler/XRef.cc +@@ -1548,11 +1548,31 @@ void XRef::readXRefUntil(int untilEntryNum, std::vector *xrefStreamObjsNum) + } + } + ++namespace { ++ ++struct DummyXRefEntry : XRefEntry { ++ DummyXRefEntry() { ++ offset = 0; ++ gen = -1; ++ type = xrefEntryNone; ++ flags = 0; ++ } ++}; ++ ++DummyXRefEntry dummyXRefEntry; ++ ++} ++ + XRefEntry *XRef::getEntry(int i, GBool complainIfMissing) + { + if (i >= size || entries[i].type == xrefEntryNone) { + + if ((!xRefStream) && mainXRefEntriesOffset) { ++ if (unlikely(i >= capacity)) { ++ error(errInternal, -1, "Request for out-of-bounds XRef entry [{0:d}]", i); ++ return &dummyXRefEntry; ++ } ++ + if (!parseEntry(mainXRefEntriesOffset + 20*i, &entries[i])) { + error(errSyntaxError, -1, "Failed to parse XRef entry [{0:d}].", i); + } +@@ -1563,12 +1583,7 @@ XRefEntry *XRef::getEntry(int i, bool complainIfMissing) + // We might have reconstructed the xref + // Check again i is in bounds + if (unlikely(i >= size)) { +- static XRefEntry dummy; +- dummy.offset = 0; +- dummy.gen = -1; +- dummy.type = xrefEntryNone; +- dummy.flags = 0; +- return &dummy; ++ return &dummyXRefEntry; + } + + if (entries[i].type == xrefEntryNone) { +-- +2.20.1 + diff --git a/SOURCES/poppler-0.66.0-embedded-file-check.patch b/SOURCES/poppler-0.66.0-embedded-file-check.patch new file mode 100644 index 0000000..a32707f --- /dev/null +++ b/SOURCES/poppler-0.66.0-embedded-file-check.patch @@ -0,0 +1,71 @@ +From 614514f577bbe676f736afcd8065892df8391315 Mon Sep 17 00:00:00 2001 +From: Marek Kasik +Date: Fri, 20 Apr 2018 11:38:13 +0200 +Subject: [PATCH] Fix crash on missing embedded file + +Check whether an embedded file is actually present in the PDF +and show warning in that case. + +https://bugs.freedesktop.org/show_bug.cgi?id=106137 +https://gitlab.freedesktop.org/poppler/poppler/issues/236 +--- + glib/poppler-attachment.cc | 26 +++++++++++++++++--------- + glib/poppler-document.cc | 3 ++- + 2 files changed, 19 insertions(+), 10 deletions(-) + +diff --git a/glib/poppler-attachment.cc b/glib/poppler-attachment.cc +index c6502e9d..11ba5bb5 100644 +--- a/glib/poppler-attachment.cc ++++ b/glib/poppler-attachment.cc +@@ -111,17 +111,25 @@ _poppler_attachment_new (FileSpec *emb_file) + attachment->description = _poppler_goo_string_to_utf8 (emb_file->getDescription ()); + + embFile = emb_file->getEmbeddedFile(); +- attachment->size = embFile->size (); ++ if (embFile != NULL && embFile->streamObject()->isStream()) ++ { ++ attachment->size = embFile->size (); + +- if (embFile->createDate ()) +- _poppler_convert_pdf_date_to_gtime (embFile->createDate (), (time_t *)&attachment->ctime); +- if (embFile->modDate ()) +- _poppler_convert_pdf_date_to_gtime (embFile->modDate (), (time_t *)&attachment->mtime); ++ if (embFile->createDate ()) ++ _poppler_convert_pdf_date_to_gtime (embFile->createDate (), (time_t *)&attachment->ctime); ++ if (embFile->modDate ()) ++ _poppler_convert_pdf_date_to_gtime (embFile->modDate (), (time_t *)&attachment->mtime); + +- if (embFile->checksum () && embFile->checksum ()->getLength () > 0) +- attachment->checksum = g_string_new_len (embFile->checksum ()->getCString (), +- embFile->checksum ()->getLength ()); +- priv->obj_stream = embFile->streamObject()->copy(); ++ if (embFile->checksum () && embFile->checksum ()->getLength () > 0) ++ attachment->checksum = g_string_new_len (embFile->checksum ()->getCString (), ++ embFile->checksum ()->getLength ()); ++ priv->obj_stream = embFile->streamObject()->copy(); ++ } ++ else ++ { ++ g_warning ("Missing stream object for embedded file"); ++ g_clear_object (&attachment); ++ } + + return attachment; + } +diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc +index b343eb90..df0aa47f 100644 +--- a/glib/poppler-document.cc ++++ b/glib/poppler-document.cc +@@ -666,7 +666,8 @@ poppler_document_get_attachments (PopplerDocument *document) + attachment = _poppler_attachment_new (emb_file); + delete emb_file; + +- retval = g_list_prepend (retval, attachment); ++ if (attachment != NULL) ++ retval = g_list_prepend (retval, attachment); + } + return g_list_reverse (retval); + } +-- +2.17.0 + diff --git a/SOURCES/poppler-0.66.0-filespec.patch b/SOURCES/poppler-0.66.0-filespec.patch new file mode 100644 index 0000000..bfaba8f --- /dev/null +++ b/SOURCES/poppler-0.66.0-filespec.patch @@ -0,0 +1,35 @@ +From de0c0b8324e776f0b851485e0fc9622fc35695b7 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Sat, 29 Dec 2018 01:25:17 +0100 +Subject: [PATCH] FileSpec: Move the fileSpec.dictLookup call inside + fileSpec.isDict if + +Fixes #704 +--- + poppler/FileSpec.cc | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/poppler/FileSpec.cc b/poppler/FileSpec.cc +index 8a8b9e7e..7c12da63 100644 +--- a/poppler/FileSpec.cc ++++ b/poppler/FileSpec.cc +@@ -133,11 +133,12 @@ FileSpec::FileSpec(const Object *fileSpecA) + return; + } + } +- } + +- obj1 = fileSpec.dictLookup("Desc"); +- if (obj1.isString()) +- desc = obj1.getString()->copy(); ++ obj1 = fileSpec.dictLookup("Desc"); ++ if (obj1.isString()) { ++ desc = obj1.getString()->copy(); ++ } ++ } + } + + FileSpec::~FileSpec() +-- +2.20.1 + diff --git a/SOURCES/poppler-0.66.0-image-stream-getline.patch b/SOURCES/poppler-0.66.0-image-stream-getline.patch new file mode 100644 index 0000000..ce20c07 --- /dev/null +++ b/SOURCES/poppler-0.66.0-image-stream-getline.patch @@ -0,0 +1,27 @@ +From f4136a6353162db249f63ddb0f20611622ab61b4 Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Wed, 27 Feb 2019 19:43:22 +0100 +Subject: [PATCH] ImageStream::getLine: fix crash on broken files + +Fixes #728 +--- + poppler/Stream.cc | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/poppler/Stream.cc b/poppler/Stream.cc +index 33537b0e..a41435ab 100644 +--- a/poppler/Stream.cc ++++ b/poppler/Stream.cc +@@ -496,6 +496,9 @@ unsigned char *ImageStream::getLine() { + } + + int readChars = str->doGetChars(inputLineSize, inputLine); ++ if (unlikely(readChars == -1)) { ++ readChars = 0; ++ } + for ( ; readChars < inputLineSize; readChars++) inputLine[readChars] = EOF; + if (nBits == 1) { + p = inputLine; +-- +2.20.1 + diff --git a/SOURCES/poppler-0.66.0-jpeg2000-component-size.patch b/SOURCES/poppler-0.66.0-jpeg2000-component-size.patch new file mode 100644 index 0000000..2ad86a8 --- /dev/null +++ b/SOURCES/poppler-0.66.0-jpeg2000-component-size.patch @@ -0,0 +1,41 @@ +From 89a5367d49b2556a2635dbb6d48d6a6b182a2c6c Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Thu, 23 May 2019 00:54:29 +0200 +Subject: [PATCH] JPEG2000Stream: fail gracefully if not all components have + the same WxH + +I think this is just a mistake, or at least the only file we have with +this scenario is a fuzzed one +--- + poppler/JPEG2000Stream.cc | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/poppler/JPEG2000Stream.cc b/poppler/JPEG2000Stream.cc +index 15bbcae4..0eea3a2d 100644 +--- a/poppler/JPEG2000Stream.cc ++++ b/poppler/JPEG2000Stream.cc +@@ -4,7 +4,7 @@ + // + // A JPX stream decoder using OpenJPEG + // +-// Copyright 2008-2010, 2012, 2017, 2018 Albert Astals Cid ++// Copyright 2008-2010, 2012, 2017-2019 Albert Astals Cid + // Copyright 2011 Daniel Glöckner + // Copyright 2014, 2016 Thomas Freitag + // Copyright 2013, 2014 Adrian Johnson +@@ -253,6 +253,12 @@ void JPXStream::init() + close(); + break; + } ++ const int componentPixels = priv->image->comps[component].w * priv->image->comps[component].h; ++ if (componentPixels != priv->npixels) { ++ error(errSyntaxWarning, -1, "Component {0:d} has different WxH than component 0", component); ++ close(); ++ break; ++ } + unsigned char *cdata = (unsigned char *)priv->image->comps[component].data; + int adjust = 0; + int depth = priv->image->comps[component].prec; +-- +2.21.0 + diff --git a/SOURCES/poppler-0.66.0-negative-object-number.patch b/SOURCES/poppler-0.66.0-negative-object-number.patch new file mode 100644 index 0000000..bc2fd6a --- /dev/null +++ b/SOURCES/poppler-0.66.0-negative-object-number.patch @@ -0,0 +1,25 @@ +From 004e3c10df0abda214f0c293f9e269fdd979c5ee Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Wed, 18 Jul 2018 20:31:27 +0200 +Subject: Fix crash when Object has negative number + +Spec says object number has to be > 0 and gen has to be >= 0 + +Reported by email + +diff --git a/poppler/Parser.cc b/poppler/Parser.cc +index 39c9a967..8b0093e3 100644 +--- a/poppler/Parser.cc ++++ b/poppler/Parser.cc +@@ -154,6 +154,11 @@ Object Parser::getObj(GBool simpleOnly, + const int gen = buf1.getInt(); + shift(); + shift(); ++ ++ if (unlikely(num <= 0 || gen < 0)) { ++ return Object(); ++ } ++ + return Object(num, gen); + } else { + return Object(num); diff --git a/SOURCES/poppler-0.66.0-negative-xref-indices.patch b/SOURCES/poppler-0.66.0-negative-xref-indices.patch new file mode 100644 index 0000000..d0cf40d --- /dev/null +++ b/SOURCES/poppler-0.66.0-negative-xref-indices.patch @@ -0,0 +1,29 @@ +From b54e1fc3e0d2600621a28d50f9f085b9e38619c2 Mon Sep 17 00:00:00 2001 +From: Adam Reichold +Date: Fri, 1 Feb 2019 08:42:27 +0100 +Subject: [PATCH] Also defend against requests for negative XRef indices. + oss-fuzz/12797 + +--- + poppler/XRef.cc | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/poppler/XRef.cc b/poppler/XRef.cc +index d042d1f4..ac2cd0ce 100644 +--- a/poppler/XRef.cc ++++ b/poppler/XRef.cc +@@ -1565,6 +1565,11 @@ DummyXRefEntry dummyXRefEntry; + + XRefEntry *XRef::getEntry(int i, GBool complainIfMissing) + { ++ if (unlikely(i < 0)) { ++ error(errInternal, -1, "Request for invalid XRef entry [{0:d}]", i); ++ return &dummyXRefEntry; ++ } ++ + if (i >= size || entries[i].type == xrefEntryNone) { + + if ((!xRefStream) && mainXRefEntriesOffset) { +-- +2.20.1 + diff --git a/SOURCES/poppler-0.66.0-nss.patch b/SOURCES/poppler-0.66.0-nss.patch new file mode 100644 index 0000000..001e528 --- /dev/null +++ b/SOURCES/poppler-0.66.0-nss.patch @@ -0,0 +1,1072 @@ +diff --git a/config.h.cmake b/config.h.cmake +index 7989cbfb..6f5e147e 100644 +--- a/config.h.cmake ++++ b/config.h.cmake +@@ -24,9 +24,6 @@ + /* Use zlib instead of builtin zlib decoder to uncompress flate streams. */ + #cmakedefine ENABLE_ZLIB_UNCOMPRESS 1 + +-/* Build against libnss3 for digital signature validation */ +-#cmakedefine ENABLE_NSS3 1 +- + /* Use cairo for rendering. */ + #cmakedefine HAVE_CAIRO 1 + +diff --git a/poppler/Decrypt.cc b/poppler/Decrypt.cc +index 16476f4f..9f4adda3 100644 +--- a/poppler/Decrypt.cc ++++ b/poppler/Decrypt.cc +@@ -39,17 +39,33 @@ + #include "goo/grandom.h" + #include "Decrypt.h" + #include "Error.h" +- ++#ifdef ENABLE_NSS3 ++#include ++#include ++#include ++#endif ++ ++#ifdef ENABLE_NSS3 ++static PK11Context *rc4InitContext(const Guchar *key, int keyLen); ++static Guchar rc4DecryptByte(PK11Context *context, Guchar c); ++#else + static void rc4InitKey(Guchar *key, int keyLen, Guchar *state); + static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c); ++#endif + + static GBool aesReadBlock(Stream *str, Guchar *in, GBool addPadding); + ++#ifdef ENABLE_NSS3 ++static PK11Context *aesInitContext(Guchar *in, Guchar *objKey, int objKeyLength, GBool decrypt); ++#else + static void aesKeyExpansion(DecryptAESState *s, Guchar *objKey, int objKeyLen, GBool decrypt); ++#endif + static void aesEncryptBlock(DecryptAESState *s, Guchar *in); + static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last); + ++#ifndef ENABLE_NSS3 + static void aes256KeyExpansion(DecryptAES256State *s, Guchar *objKey, int objKeyLen, GBool decrypt); ++#endif + static void aes256EncryptBlock(DecryptAES256State *s, Guchar *in); + static void aes256DecryptBlock(DecryptAES256State *s, Guchar *in, GBool last); + +@@ -70,6 +86,31 @@ static const Guchar passwordPad[32] = { + // Decrypt + //------------------------------------------------------------------------ + ++#ifdef ENABLE_NSS3 ++static void shutdownNSS() ++{ ++ if (NSS_Shutdown() != SECSuccess) { ++ error(errInternal, -1, "NSS shutdown failed: {0:s}", ++ PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); ++ } ++} ++ ++static GBool initNSS() { ++ if (NSS_IsInitialized()) { ++ return gTrue; ++ } else { ++ if (NSS_NoDB_Init(".") != SECSuccess) { ++ error(errInternal, -1, "NSS initialization failed: {0:s}", ++ PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); ++ return gFalse; ++ } else { ++ atexit(shutdownNSS); ++ return gTrue; ++ } ++ } ++} ++#endif ++ + GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, + GooString *ownerKey, GooString *userKey, + GooString *ownerEnc, GooString *userEnc, +@@ -80,13 +121,21 @@ GBool Decrypt::makeFileKey(int encVersio + DecryptAES256State state; + Guchar test[127 + 56], test2[32]; + GooString *userPassword2; +- Guchar fState[256]; + Guchar tmpKey[16]; +- Guchar fx, fy; + int len, i, j; ++#ifdef ENABLE_NSS3 ++ PK11Context *rc4Context; ++#else ++ Guchar fState[256]; ++ Guchar fx, fy; ++#endif + + *ownerPasswordOk = gFalse; + ++#ifdef ENABLE_NSS3 ++ initNSS(); ++#endif ++ + if (encRevision == 5 || encRevision == 6) { + + // check the owner password +@@ -115,15 +164,27 @@ GBool Decrypt::makeFileKey(int encVersio + //test contains the initial SHA-256 hash input K. + revision6Hash(ownerPassword, test, userKey->getCString()); + } ++#ifndef ENABLE_NSS3 + aes256KeyExpansion(&state, test, 32, gTrue); ++#endif + for (i = 0; i < 16; ++i) { + state.cbc[i] = 0; + } ++#ifdef ENABLE_NSS3 ++ state.context = aesInitContext(state.cbc, test, 32, gTrue); ++ if (state.context) { ++#endif + aes256DecryptBlock(&state, (Guchar *)ownerEnc->getCString(), gFalse); + memcpy(fileKey, state.buf, 16); + aes256DecryptBlock(&state, (Guchar *)ownerEnc->getCString() + 16, + gFalse); + memcpy(fileKey + 16, state.buf, 16); ++#ifdef ENABLE_NSS3 ++ PK11_DestroyContext(state.context, PR_TRUE); ++ } else { ++ return gFalse; ++ } ++#endif + + *ownerPasswordOk = gTrue; + return gTrue; +@@ -156,15 +217,27 @@ GBool Decrypt::makeFileKey(int encVersio + //user key is not used in computing intermediate user key. + revision6Hash(userPassword, test, nullptr); + } ++#ifndef ENABLE_NSS3 + aes256KeyExpansion(&state, test, 32, gTrue); ++#endif + for (i = 0; i < 16; ++i) { + state.cbc[i] = 0; + } ++#ifdef ENABLE_NSS3 ++ state.context = aesInitContext(state.cbc, test, 32, gTrue); ++ if (state.context) { ++#endif + aes256DecryptBlock(&state, (Guchar *)userEnc->getCString(), gFalse); + memcpy(fileKey, state.buf, 16); + aes256DecryptBlock(&state, (Guchar *)userEnc->getCString() + 16, + gFalse); + memcpy(fileKey + 16, state.buf, 16); ++#ifdef ENABLE_NSS3 ++ PK11_DestroyContext(state.context, PR_TRUE); ++ } else { ++ return gFalse; ++ } ++#endif + + return gTrue; + } +@@ -189,22 +262,41 @@ GBool Decrypt::makeFileKey(int encVersio + } + } + if (encRevision == 2) { ++#ifdef ENABLE_NSS3 ++ rc4Context = rc4InitContext(test, keyLength); ++ if (rc4Context) { ++ for (i = 0; i < 32; ++i) ++ test2[i] = rc4DecryptByte(rc4Context, ownerKey->getChar(i)); ++ PK11_DestroyContext(rc4Context, PR_TRUE); ++ } ++#else + rc4InitKey(test, keyLength, fState); + fx = fy = 0; + for (i = 0; i < 32; ++i) { + test2[i] = rc4DecryptByte(fState, &fx, &fy, ownerKey->getChar(i)); + } ++#endif + } else { + memcpy(test2, ownerKey->getCString(), 32); + for (i = 19; i >= 0; --i) { + for (j = 0; j < keyLength; ++j) { + tmpKey[j] = test[j] ^ i; + } ++#ifdef ENABLE_NSS3 ++ rc4Context = rc4InitContext(tmpKey, keyLength); ++ if (rc4Context) { ++ for (j = 0; j < 32; ++j) { ++ test2[j] = rc4DecryptByte(rc4Context, test2[j]); ++ } ++ PK11_DestroyContext(rc4Context, PR_TRUE); ++ } ++#else + rc4InitKey(tmpKey, keyLength, fState); + fx = fy = 0; + for (j = 0; j < 32; ++j) { + test2[j] = rc4DecryptByte(fState, &fx, &fy, test2[j]); + } ++#endif + } + } + userPassword2 = new GooString((char *)test2, 32); +@@ -232,11 +324,15 @@ GBool Decrypt::makeFileKey2(int encVersi + GBool encryptMetadata) { + Guchar *buf; + Guchar test[32]; +- Guchar fState[256]; + Guchar tmpKey[16]; +- Guchar fx, fy; + int len, i, j; +- GBool ok; ++ GBool ok = gTrue; ++#ifdef ENABLE_NSS3 ++ PK11Context *rc4Context; ++#else ++ Guchar fState[256]; ++ Guchar fx, fy; ++#endif + + // generate file key + buf = (Guchar *)gmalloc(72 + fileID->getLength()); +@@ -273,28 +369,52 @@ GBool Decrypt::makeFileKey2(int encVersi + + // test user password + if (encRevision == 2) { ++#ifdef ENABLE_NSS3 ++ rc4Context = rc4InitContext(fileKey, keyLength); ++ if (rc4Context) { ++ for (i = 0; i < 32; ++i) ++ test[i] = rc4DecryptByte(rc4Context, userKey->getChar(i)); ++ PK11_DestroyContext(rc4Context, PR_TRUE); ++ } else { ++ ok = gFalse; ++ } ++#else + rc4InitKey(fileKey, keyLength, fState); + fx = fy = 0; + for (i = 0; i < 32; ++i) { + test[i] = rc4DecryptByte(fState, &fx, &fy, userKey->getChar(i)); + } +- ok = memcmp(test, passwordPad, 32) == 0; ++#endif ++ if (ok) ++ ok = memcmp(test, passwordPad, 32) == 0; + } else if (encRevision == 3) { + memcpy(test, userKey->getCString(), 32); + for (i = 19; i >= 0; --i) { + for (j = 0; j < keyLength; ++j) { + tmpKey[j] = fileKey[j] ^ i; + } ++#ifdef ENABLE_NSS3 ++ rc4Context = rc4InitContext(tmpKey, keyLength); ++ if (rc4Context) { ++ for (j = 0; j < 32; ++j) ++ test[j] = rc4DecryptByte(rc4Context, test[j]); ++ PK11_DestroyContext(rc4Context, PR_TRUE); ++ } else { ++ ok = gFalse; ++ } ++#else + rc4InitKey(tmpKey, keyLength, fState); + fx = fy = 0; + for (j = 0; j < 32; ++j) { + test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]); + } ++#endif + } + memcpy(buf, passwordPad, 32); + memcpy(buf + 32, fileID->getCString(), fileID->getLength()); + md5(buf, 32 + fileID->getLength(), buf); +- ok = memcmp(test, buf, 16) == 0; ++ if (ok) ++ ok = memcmp(test, buf, 16) == 0; + } else { + ok = gFalse; + } +@@ -334,6 +454,9 @@ BaseCryptStream::BaseCryptStream(Stream + if ((objKeyLength = keyLength + 5) > 16) { + objKeyLength = 16; + } ++#ifdef ENABLE_NSS3 ++ state.rc4.context = nullptr; ++#endif + break; + case cryptAES: + objKey[keyLength] = objNum & 0xff; +@@ -349,9 +472,15 @@ BaseCryptStream::BaseCryptStream(Stream + if ((objKeyLength = keyLength + 5) > 16) { + objKeyLength = 16; + } ++#ifdef ENABLE_NSS3 ++ state.aes.context = nullptr; ++#endif + break; + case cryptAES256: + objKeyLength = keyLength; ++#ifdef ENABLE_NSS3 ++ state.aes256.context = nullptr; ++#endif + break; + case cryptNone: + break; +@@ -359,9 +488,32 @@ BaseCryptStream::BaseCryptStream(Stream + + charactersRead = 0; + autoDelete = gTrue; ++ ++#ifdef ENABLE_NSS3 ++ initNSS(); ++#endif + } + + BaseCryptStream::~BaseCryptStream() { ++#ifdef ENABLE_NSS3 ++ switch (algo) { ++ case cryptRC4: ++ if (state.rc4.context) ++ PK11_DestroyContext(state.rc4.context, PR_TRUE); ++ break; ++ case cryptAES: ++ if (state.aes.context) ++ PK11_DestroyContext(state.aes.context, PR_TRUE); ++ break; ++ case cryptAES256: ++ if (state.aes256.context) ++ PK11_DestroyContext(state.aes256.context, PR_TRUE); ++ break; ++ default: ++ break; ++ } ++#endif ++ + if (autoDelete) { + delete str; + } +@@ -424,18 +576,40 @@ void EncryptStream::reset() { + + switch (algo) { + case cryptRC4: ++#ifdef ENABLE_NSS3 ++ if (state.rc4.context) ++ PK11_DestroyContext(state.rc4.context, PR_TRUE); ++ state.rc4.context = rc4InitContext(objKey, objKeyLength); ++#else + state.rc4.x = state.rc4.y = 0; + rc4InitKey(objKey, objKeyLength, state.rc4.state); ++#endif + break; + case cryptAES: ++#ifdef ENABLE_NSS3 ++ memcpy(state.aes.buf, state.aes.cbc, 16); // Copy CBC IV to buf ++ if (state.aes.context) ++ PK11_DestroyContext(state.aes.context, PR_TRUE); ++ state.aes.context = aesInitContext(state.aes.cbc, objKey, objKeyLength, ++ gFalse); ++#else + aesKeyExpansion(&state.aes, objKey, objKeyLength, gFalse); + memcpy(state.aes.buf, state.aes.cbc, 16); // Copy CBC IV to buf ++#endif + state.aes.bufIdx = 0; + state.aes.paddingReached = gFalse; + break; + case cryptAES256: ++#ifdef ENABLE_NSS3 ++ memcpy(state.aes256.buf, state.aes256.cbc, 16); // Copy CBC IV to buf ++ if (state.aes256.context) ++ PK11_DestroyContext(state.aes256.context, PR_TRUE); ++ state.aes256.context = aesInitContext(state.aes256.cbc, objKey, objKeyLength, ++ gFalse); ++#else + aes256KeyExpansion(&state.aes256, objKey, objKeyLength, gFalse); + memcpy(state.aes256.buf, state.aes256.cbc, 16); // Copy CBC IV to buf ++#endif + state.aes256.bufIdx = 0; + state.aes256.paddingReached = gFalse; + break; +@@ -456,7 +630,11 @@ int EncryptStream::lookChar() { + case cryptRC4: + if ((c = str->getChar()) != EOF) { + // RC4 is XOR-based: the decryption algorithm works for encryption too ++#ifdef ENABLE_NSS3 ++ c = rc4DecryptByte(state.rc4.context, (Guchar)c); ++#else + c = rc4DecryptByte(state.rc4.state, &state.rc4.x, &state.rc4.y, (Guchar)c); ++#endif + } + break; + case cryptAES: +@@ -506,21 +684,47 @@ void DecryptStream::reset() { + + switch (algo) { + case cryptRC4: ++#ifdef ENABLE_NSS3 ++ if (state.rc4.context) ++ PK11_DestroyContext(state.rc4.context, PR_TRUE); ++ state.rc4.context = rc4InitContext(objKey, objKeyLength); ++#else + state.rc4.x = state.rc4.y = 0; + rc4InitKey(objKey, objKeyLength, state.rc4.state); ++#endif + break; + case cryptAES: ++#ifdef ENABLE_NSS3 ++ if (state.aes.context) ++ PK11_DestroyContext(state.aes.context, PR_TRUE); ++ for (i = 0; i < 16; ++i) { ++ state.aes.cbc[i] = str->getChar(); ++ } ++ state.aes.context = aesInitContext(state.aes.cbc, objKey, objKeyLength, ++ gTrue); ++#else + aesKeyExpansion(&state.aes, objKey, objKeyLength, gTrue); + for (i = 0; i < 16; ++i) { + state.aes.cbc[i] = str->getChar(); + } ++#endif + state.aes.bufIdx = 16; + break; + case cryptAES256: ++#ifdef ENABLE_NSS3 ++ if (state.aes256.context) ++ PK11_DestroyContext(state.aes256.context, PR_TRUE); ++ for (i = 0; i < 16; ++i) { ++ state.aes256.cbc[i] = str->getChar(); ++ } ++ state.aes256.context = aesInitContext(state.aes256.cbc, objKey, objKeyLength, ++ gTrue); ++#else + aes256KeyExpansion(&state.aes256, objKey, objKeyLength, gTrue); + for (i = 0; i < 16; ++i) { + state.aes256.cbc[i] = str->getChar(); + } ++#endif + state.aes256.bufIdx = 16; + break; + case cryptNone: +@@ -539,10 +743,21 @@ int DecryptStream::lookChar() { + switch (algo) { + case cryptRC4: + if ((c = str->getChar()) != EOF) { ++#ifdef ENABLE_NSS3 ++ if (unlikely(state.rc4.context == nullptr)) ++ c = EOF; ++ else ++ c = rc4DecryptByte(state.rc4.context, (Guchar)c); ++#else + c = rc4DecryptByte(state.rc4.state, &state.rc4.x, &state.rc4.y, (Guchar)c); ++#endif + } + break; + case cryptAES: ++#ifdef ENABLE_NSS3 ++ if (unlikely(state.aes.context == nullptr)) ++ break; ++#endif + if (state.aes.bufIdx == 16) { + if (aesReadBlock(str, in, gFalse)) { + aesDecryptBlock(&state.aes, in, str->lookChar() == EOF); +@@ -555,6 +770,10 @@ int DecryptStream::lookChar() { + } + break; + case cryptAES256: ++#ifdef ENABLE_NSS3 ++ if (unlikely(state.aes256.context == nullptr)) ++ break; ++#endif + if (state.aes256.bufIdx == 16) { + if (aesReadBlock(str, in, gFalse)) { + aes256DecryptBlock(&state.aes256, in, str->lookChar() == EOF); +@@ -576,6 +795,175 @@ int DecryptStream::lookChar() { + // RC4-compatible decryption + //------------------------------------------------------------------------ + ++#ifdef ENABLE_NSS3 ++/* ++ * This function turns given key into token key (compared to a session key ++ * which is prohibited in FIPS mode). ++ */ ++static PK11SymKey *tokenizeKey(const Guchar *key, int keyLen, ++ CK_ATTRIBUTE_TYPE operation) { ++ CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC_PAD; ++ PK11SlotInfo *slot; ++ PK11SymKey *wrappingKey = nullptr; ++ PK11SymKey *symKey = nullptr; ++ PK11SymKey *token = nullptr; ++ SECStatus retval; ++ SECItem *secParam = nullptr; ++ SECItem ivItem, wrappedKey; ++ Guchar output[48]; // Buffer to hold 256 bit key + padding ++ Guchar iv[16]; // Initialization vector for AES ++ Guint outputLength; ++ int i; ++ ++ slot = PK11_GetBestSlot(CKM_AES_KEY_GEN, nullptr); ++ if (slot == nullptr) { ++ error(errInternal, -1, "Unable to find security device (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ // Generate random key for wrapping of given key by AES-256 ++ wrappingKey = PK11_KeyGen(slot, CKM_AES_KEY_GEN, nullptr, 32, nullptr); ++ if (wrappingKey == nullptr) { ++ error(errInternal, -1, "Failed to generate wrapping key (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ for (i = 0; i < 16; i++) ++ iv[i] = i; ++ ++ ivItem.type = siBuffer; ++ ivItem.data = iv; ++ ivItem.len = 16; ++ ++ secParam = PK11_ParamFromIV(cipherMech, &ivItem); ++ if (secParam == nullptr) { ++ error(errInternal, -1, "Failed to set up PKCS11 param (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ // Encrypt given key ++ retval = PK11_Encrypt(wrappingKey, ++ cipherMech, ++ secParam, ++ output, ++ &outputLength, ++ sizeof(output), ++ key, ++ keyLen); ++ if (retval != SECSuccess) { ++ error(errInternal, -1, "Failed to encrypt key (err {0:d})", ++ PR_GetError()); ++ } ++ ++ wrappedKey.type = siBuffer; ++ wrappedKey.data = output; ++ wrappedKey.len = outputLength; ++ ++ // Unwrap the wrapped key to token so it can be used in FIPS mode ++ token = PK11_UnwrapSymKey(wrappingKey, ++ cipherMech, ++ &ivItem, ++ &wrappedKey, ++ operation, ++ CKA_UNWRAP, ++ keyLen); ++ ++ if (token == nullptr) { ++ error(errInternal, -1, "Failed to unwrap symmetric key (err {0:d})", ++ PR_GetError()); ++ } ++ ++err: ++ if (secParam != nullptr) ++ SECITEM_FreeItem(secParam, PR_TRUE); ++ ++ if (wrappingKey != nullptr) ++ PK11_FreeSymKey(wrappingKey); ++ ++ if (symKey != nullptr) ++ PK11_FreeSymKey(symKey); ++ ++ if (slot != nullptr) ++ PK11_FreeSlot(slot); ++ ++ return token; ++} ++ ++static PK11Context *rc4InitContext(const Guchar *key, int keyLen) { ++ CK_MECHANISM_TYPE cipherMech = CKM_RC4; ++ PK11SlotInfo *slot = nullptr; ++ PK11SymKey *symKey = nullptr; ++ SECItem *secParam = nullptr; ++ PK11Context *context = nullptr; ++ ++ slot = PK11_GetBestSlot(cipherMech, nullptr); ++ if (slot == nullptr) { ++ error(errInternal, -1, "Unable to find security device (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ symKey = tokenizeKey(key, keyLen, cipherMech); ++ if (symKey == nullptr) { ++ error(errInternal, -1, "Failed to create token from key (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ secParam = PK11_ParamFromIV(cipherMech, nullptr); ++ if (secParam == nullptr) { ++ error(errInternal, -1, "Failed to set up PKCS11 param (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ context = PK11_CreateContextBySymKey(cipherMech, ++ CKA_DECRYPT, ++ symKey, ++ secParam); ++ if (context == nullptr) { ++ error(errInternal, -1, "Failed to create context (err {0:d})", ++ PR_GetError()); ++ } ++ ++err: ++ if (secParam != nullptr) ++ SECITEM_FreeItem(secParam, PR_TRUE); ++ ++ if (symKey != nullptr) ++ PK11_FreeSymKey(symKey); ++ ++ if (slot != nullptr) ++ PK11_FreeSlot(slot); ++ ++ return context; ++} ++ ++static Guchar rc4DecryptByte(PK11Context *context, Guchar c) { ++ Guchar outputChar = 0; ++ SECStatus retval; ++ int outputLength; ++ ++ retval = PK11_CipherOp(context, ++ &outputChar, ++ &outputLength, ++ 1, ++ &c, ++ 1); ++ ++ if (retval != SECSuccess) { ++ error(errInternal, -1, "Failed to decrypt byte (err {0:d})", ++ PR_GetError()); ++ } ++ ++ return outputChar; ++} ++ ++#else ++ + static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) { + Guchar index1, index2; + Guchar t; +@@ -609,6 +997,8 @@ static Guchar rc4DecryptByte(Guchar *sta + return c ^ state[(tx + ty) % 256]; + } + ++#endif ++ + //------------------------------------------------------------------------ + // AES decryption + //------------------------------------------------------------------------ +@@ -639,6 +1029,178 @@ static GBool aesReadBlock(Stream *str, G + } + } + ++#ifdef ENABLE_NSS3 ++ ++static PK11Context *aesInitContext(Guchar *in, Guchar *objKey, ++ int objKeyLength, GBool decrypt) { ++ CK_MECHANISM_TYPE cipherMech = CKM_AES_CBC; ++ CK_ATTRIBUTE_TYPE operationType = decrypt ? CKA_DECRYPT : CKA_ENCRYPT; ++ PK11SlotInfo *slot; ++ PK11SymKey *symKey = nullptr; ++ SECItem *secParam = nullptr; ++ PK11Context *context = nullptr; ++ SECItem ivItem; ++ ++ slot = PK11_GetBestSlot(cipherMech, nullptr); ++ if (slot == nullptr) { ++ error(errInternal, -1, "Unable to find security device (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ symKey = tokenizeKey(objKey, objKeyLength, cipherMech); ++ if (symKey == nullptr) { ++ error(errInternal, -1, "Failed to create token from key (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ ivItem.type = siBuffer; ++ ivItem.data = in; ++ ivItem.len = 16; ++ ++ secParam = PK11_ParamFromIV(cipherMech, &ivItem); ++ if (secParam == nullptr) { ++ error(errInternal, -1, "Failed to set up PKCS11 param (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ context = PK11_CreateContextBySymKey(cipherMech, ++ operationType, ++ symKey, ++ secParam); ++ ++err: ++ if (secParam != nullptr) ++ SECITEM_FreeItem(secParam, PR_TRUE); ++ ++ if (symKey != nullptr) ++ PK11_FreeSymKey(symKey); ++ ++ if (slot != nullptr) ++ PK11_FreeSlot(slot); ++ ++ return context; ++} ++ ++static void aesEncryptBlock(DecryptAESState *s, Guchar *in) { ++ SECStatus rv; ++ int outputLength; ++ ++ rv = PK11_CipherOp(s->context, ++ s->buf, ++ &outputLength, ++ 16, ++ in, ++ 16); ++ ++ if (rv != SECSuccess) { ++ error(errInternal, -1, "Failed to encrypt input block (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ s->bufIdx = 0; ++ ++err: ++ return; ++} ++ ++static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last) { ++ SECStatus rv1; ++ int outputLen; ++ int n, i; ++ ++ rv1 = PK11_CipherOp(s->context, ++ s->buf, ++ &outputLen, ++ 16, ++ in, ++ 16); ++ ++ if (rv1 != SECSuccess) { ++ error(errInternal, -1, "Failed to decrypt input block (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ s->bufIdx = 0; ++ if (last) { ++ n = s->buf[15]; ++ if (n < 1 || n > 16) { // this should never happen ++ n = 16; ++ } ++ for (i = 15; i >= n; --i) { ++ s->buf[i] = s->buf[i-n]; ++ } ++ s->bufIdx = n; ++ } ++ ++err: ++ return; ++} ++ ++static void aes256EncryptBlock(DecryptAES256State *s, Guchar *in) { ++ SECStatus rv; ++ int outputLength; ++ ++ rv = PK11_CipherOp(s->context, ++ s->buf, ++ &outputLength, ++ 16, ++ in, ++ 16); ++ ++ if (rv != SECSuccess) { ++ error(errInternal, -1, "Failed to encrypt input block (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ s->bufIdx = 0; ++ ++err: ++ return; ++} ++ ++static void aes256DecryptBlock(DecryptAES256State *s, Guchar *in, ++ GBool last) { ++ SECStatus rv1; ++ int outputLen; ++ int n, i; ++ ++ rv1 = PK11_CipherOp(s->context, ++ s->buf, ++ &outputLen, ++ 16, ++ in, ++ 16); ++ ++ if (rv1 != SECSuccess) { ++ error(errInternal, -1, "Failed to decrypt input block (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } ++ ++ s->bufIdx = 0; ++ if (last) { ++ n = s->buf[15]; ++ if (n < 1 || n > 16) { // this should never happen ++ n = 16; ++ } ++ for (i = 15; i >= n; --i) { ++ s->buf[i] = s->buf[i-n]; ++ } ++ s->bufIdx = n; ++ } ++ ++err: ++ return; ++} ++ ++#else ++ + static const Guchar sbox[256] = { + 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, + 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, +@@ -1121,10 +1683,33 @@ static void aes256DecryptBlock(DecryptAE + } + } + ++#endif ++ + //------------------------------------------------------------------------ + // MD5 message digest + //------------------------------------------------------------------------ + ++#ifdef ENABLE_NSS3 ++static void hashFunc(const Guchar *msg, int msgLen, Guchar *hash, ++ HASH_HashType type) { ++ HASHContext *context; ++ Guint hashLen = 0; ++ ++ if (!initNSS()) ++ return; ++ ++ context = HASH_Create(type); ++ if (context == nullptr) ++ return; ++ ++ HASH_Begin(context); ++ HASH_Update(context, msg, msgLen); ++ HASH_End(context, hash, &hashLen, HASH_ResultLen(type)); ++ HASH_Destroy(context); ++} ++ ++#else ++ + // this works around a bug in older Sun compilers + static inline Gulong rotateLeft(Gulong x, int r) { + x &= 0xffffffff; +@@ -1151,7 +1736,12 @@ static inline Gulong md5Round4(Gulong a, + return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s); + } + ++#endif ++ + void md5(Guchar *msg, int msgLen, Guchar *digest) { ++#ifdef ENABLE_NSS3 ++ hashFunc(msg, msgLen, digest, HASH_AlgMD5); ++#else + Gulong x[16] = {}; + Gulong a, b, c, d, aa, bb, cc, dd; + int n64; +@@ -1296,12 +1886,14 @@ void md5(Guchar *msg, int msgLen, Guchar + digest[13] = (Guchar)((d >>= 8) & 0xff); + digest[14] = (Guchar)((d >>= 8) & 0xff); + digest[15] = (Guchar)((d >>= 8) & 0xff); ++#endif + } + + //------------------------------------------------------------------------ + // SHA-256 hash + //------------------------------------------------------------------------ + ++#ifndef ENABLE_NSS3 + static Guint sha256K[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, + 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, +@@ -1400,8 +1992,12 @@ static void sha256HashBlock(Guchar *blk, + H[6] += g; + H[7] += h; + } ++#endif + + static void sha256(Guchar *msg, int msgLen, Guchar *hash) { ++#ifdef ENABLE_NSS3 ++ hashFunc(msg, msgLen, hash, HASH_AlgSHA256); ++#else + Guchar blk[64]; + Guint H[8]; + int blkLen, i; +@@ -1453,7 +2049,10 @@ static void sha256(Guchar *msg, int msgL + hash[i*4 + 2] = (Guchar)(H[i] >> 8); + hash[i*4 + 3] = (Guchar)H[i]; + } ++#endif + } ++ ++#ifndef ENABLE_NSS3 + //------------------------------------------------------------------------ + // SHA-512 hash (see FIPS 180-4) + //------------------------------------------------------------------------ +@@ -1557,8 +2156,12 @@ static void sha512HashBlock(Guchar *blk, + H[6] += g; + H[7] += h; + } ++#endif + + static void sha512(Guchar *msg, int msgLen, Guchar *hash) { ++#ifdef ENABLE_NSS3 ++ hashFunc(msg, msgLen, hash, HASH_AlgSHA512); ++#else + Guchar blk[128]; + uint64_t H[8]; + int blkLen = 0, i; +@@ -1622,6 +2225,7 @@ static void sha512(Guchar *msg, int msgL + hash[i*8 + 6] = (Guchar)(H[i] >> 8); + hash[i*8 + 7] = (Guchar)H[i]; + } ++#endif + } + + //------------------------------------------------------------------------ +@@ -1631,6 +2235,9 @@ static void sha512(Guchar *msg, int msgL + //1.Initial hash value is different. + //2.A 384 bit message digest is obtained by truncating the final hash value. + static void sha384(Guchar *msg, int msgLen, Guchar *hash) { ++#ifdef ENABLE_NSS3 ++ hashFunc(msg, msgLen, hash, HASH_AlgSHA384); ++#else + Guchar blk[128]; + uint64_t H[8]; + int blkLen, i; +@@ -1696,6 +2303,7 @@ static void sha384(Guchar *msg, int msgL + hash[i*8 + 6] = (Guchar)(H[i] >> 8); + hash[i*8 + 7] = (Guchar)H[i]; + } ++#endif + } + + //------------------------------------------------------------------------ +@@ -1725,7 +2333,8 @@ static void revision6Hash(GooString *inp + //a.make the string K1 + memcpy(K1, inputPassword, inputPasswordLength); + memcpy(K1 + inputPasswordLength, K , KLength); +- memcpy(K1 + inputPasswordLength + KLength, userKey, userKeyLength); ++ if (userKey) ++ memcpy(K1 + inputPasswordLength + KLength, userKey, userKeyLength); + for(int i = 1; i < 64 ; ++i) { + memcpy(K1 + (i * sequenceLength),K1,sequenceLength); + } +@@ -1735,7 +2344,11 @@ static void revision6Hash(GooString *inp + memcpy(state.buf, state.cbc, 16); // Copy CBC IV to buf + state.bufIdx = 0; + state.paddingReached = gFalse; ++#ifdef ENABLE_NSS3 ++ state.context = aesInitContext(state.cbc, aesKey, 16, gFalse); ++#else + aesKeyExpansion(&state,aesKey,16,gFalse); ++#endif + + for(int i = 0; i < (4 * sequenceLength); i++) { + aesEncryptBlock(&state,K1 + (16 * i)); +@@ -1776,6 +2389,9 @@ static void revision6Hash(GooString *inp + sha512(E, totalLength, K); + } + rounds++; ++#ifdef ENABLE_NSS3 ++ PK11_DestroyContext(state.context, PR_TRUE); ++#endif + } + // the first 32 bytes of the final K are the output of the function. + } +diff --git a/poppler/Decrypt.h b/poppler/Decrypt.h +index d4667c8c..16fa9830 100644 +--- a/poppler/Decrypt.h ++++ b/poppler/Decrypt.h +@@ -31,6 +32,9 @@ + #include "goo/GooString.h" + #include "Object.h" + #include "Stream.h" ++#ifdef ENABLE_NSS3 ++#include ++#endif + + //------------------------------------------------------------------------ + // Decrypt +@@ -73,13 +77,21 @@ private: + * previous output is kept in buf. The paddingReached field is only used in + * case of encryption. */ + struct DecryptRC4State { ++#ifdef ENABLE_NSS3 ++ PK11Context *context; ++#else + Guchar state[256]; + Guchar x, y; ++#endif + }; + + struct DecryptAESState { ++#ifdef ENABLE_NSS3 ++ PK11Context *context; ++#else + Guint w[44]; + Guchar state[16]; ++#endif + Guchar cbc[16]; + Guchar buf[16]; + GBool paddingReached; // encryption only +@@ -87,8 +99,12 @@ struct DecryptAESState { + }; + + struct DecryptAES256State { ++#ifdef ENABLE_NSS3 ++ PK11Context *context; ++#else + Guint w[60]; + Guchar state[16]; ++#endif + Guchar cbc[16]; + Guchar buf[16]; + GBool paddingReached; // encryption only +diff --git a/poppler/poppler-config.h.cmake b/poppler/poppler-config.h.cmake +index f0a5a1a0..dcaade6f 100644 +--- a/poppler/poppler-config.h.cmake ++++ b/poppler/poppler-config.h.cmake +@@ -115,6 +115,12 @@ + #cmakedefine USE_CMS 1 + #endif + ++/* Build against libnss3 for digital signature validation and ++ implementation of encryption/decryption. */ ++#ifndef ENABLE_NSS3 ++#cmakedefine ENABLE_NSS3 1 ++#endif ++ + // Also, there are preprocessor symbols in the header files + // that are used but never defined when building poppler using configure + // or cmake: DISABLE_OUTLINE, DEBUG_MEM, +--- poppler-0.66.0/CMakeLists.txt ++++ poppler-0.66.0/CMakeLists.txt +@@ -490,7 +490,7 @@ add_library(poppler STATIC ${poppler_SRC + else() + add_library(poppler ${poppler_SRCS}) + endif() +-set_target_properties(poppler PROPERTIES VERSION 77.0.0 SOVERSION 77) ++set_target_properties(poppler PROPERTIES VERSION 78.0.0 SOVERSION 78) + if(MINGW) + get_target_property(POPPLER_SOVERSION poppler SOVERSION) + set_target_properties(poppler PROPERTIES SUFFIX "-${POPPLER_SOVERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}") diff --git a/SOURCES/poppler-0.66.0-rescale-filter.patch b/SOURCES/poppler-0.66.0-rescale-filter.patch new file mode 100644 index 0000000..3dbad5c --- /dev/null +++ b/SOURCES/poppler-0.66.0-rescale-filter.patch @@ -0,0 +1,100 @@ +From 8122f6d6d409b53151a20c5578fc525ee97315e8 Mon Sep 17 00:00:00 2001 +From: Marek Kasik +Date: Thu, 21 Mar 2019 13:47:51 +0100 +Subject: [PATCH 2/2] cairo: Constrain number of cycles in rescale filter + +Pass address of the first byte after end of the source buffer +to downsample_row_box_filter() so that we can check +that we don't run out of it. + +Fixes issue #736 +--- + poppler/CairoRescaleBox.cc | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/poppler/CairoRescaleBox.cc b/poppler/CairoRescaleBox.cc +index d7615010..7fd07041 100644 +--- a/poppler/CairoRescaleBox.cc ++++ b/poppler/CairoRescaleBox.cc +@@ -62,7 +62,7 @@ + + static void downsample_row_box_filter ( + int start, int width, +- uint32_t *src, uint32_t *dest, ++ uint32_t *src, uint32_t *src_limit, uint32_t *dest, + int coverage[], int pixel_coverage) + { + /* we need an array of the pixel contribution of each destination pixel on the boundaries. +@@ -90,13 +90,13 @@ static void downsample_row_box_filter ( + /* skip to start */ + /* XXX: it might be possible to do this directly instead of iteratively, however + * the iterative solution is simple */ +- while (x < start) ++ while (x < start && src < src_limit) + { + int box = 1 << FIXED_SHIFT; + int start_coverage = coverage[x]; + box -= start_coverage; + src++; +- while (box >= pixel_coverage) ++ while (box >= pixel_coverage && src < src_limit) + { + src++; + box -= pixel_coverage; +@@ -104,7 +104,7 @@ static void downsample_row_box_filter ( + x++; + } + +- while (x < start + width) ++ while (x < start + width && src < src_limit) + { + uint32_t a = 0; + uint32_t r = 0; +@@ -121,7 +121,7 @@ static void downsample_row_box_filter ( + x++; + box -= start_coverage; + +- while (box >= pixel_coverage) ++ while (box >= pixel_coverage && src < src_limit) + { + a += ((*src >> 24) & 0xff) * pixel_coverage; + r += ((*src >> 16) & 0xff) * pixel_coverage; +@@ -135,7 +135,7 @@ static void downsample_row_box_filter ( + /* multiply by whatever is leftover + * this ensures that we don't bias down. + * i.e. start_coverage + n*pixel_coverage + box == 1 << 24 */ +- if (box > 0) ++ if (box > 0 && src < src_limit) + { + a += ((*src >> 24) & 0xff) * box; + r += ((*src >> 16) & 0xff) * box; +@@ -337,7 +337,7 @@ bool CairoRescaleBox::downScaleImage(unsigned orig_width, unsigned orig_height, + int start_coverage_y = y_coverage[dest_y]; + + getRow(src_y, scanline); +- downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x); ++ downsample_row_box_filter (start_column, width, scanline, scanline + orig_width, temp_buf + width * columns, x_coverage, pixel_coverage_x); + columns++; + src_y++; + box -= start_coverage_y; +@@ -345,7 +345,7 @@ bool CairoRescaleBox::downScaleImage(unsigned orig_width, unsigned orig_height, + while (box >= pixel_coverage_y) + { + getRow(src_y, scanline); +- downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x); ++ downsample_row_box_filter (start_column, width, scanline, scanline + orig_width, temp_buf + width * columns, x_coverage, pixel_coverage_x); + columns++; + src_y++; + box -= pixel_coverage_y; +@@ -355,7 +355,7 @@ bool CairoRescaleBox::downScaleImage(unsigned orig_width, unsigned orig_height, + if (box > 0) + { + getRow(src_y, scanline); +- downsample_row_box_filter (start_column, width, scanline, temp_buf + width * columns, x_coverage, pixel_coverage_x); ++ downsample_row_box_filter (start_column, width, scanline, scanline + orig_width, temp_buf + width * columns, x_coverage, pixel_coverage_x); + columns++; + } + +-- +2.20.1 + diff --git a/SOURCES/poppler-0.66.0-rich-media-annotation.patch b/SOURCES/poppler-0.66.0-rich-media-annotation.patch new file mode 100644 index 0000000..3730e3e --- /dev/null +++ b/SOURCES/poppler-0.66.0-rich-media-annotation.patch @@ -0,0 +1,51 @@ +From 7f87dc10b6adccd6d1b977a28b064add254aa2da Mon Sep 17 00:00:00 2001 +From: Adam Reichold +Date: Thu, 27 Dec 2018 11:54:53 +0100 +Subject: [PATCH] Do not try to construct invalid rich media annotation assets. + Closes #703 + +--- + poppler/Annot.cc | 24 +++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +diff --git a/poppler/Annot.cc b/poppler/Annot.cc +index 2e4770ab..1750dc70 100644 +--- a/poppler/Annot.cc ++++ b/poppler/Annot.cc +@@ -6418,20 +6418,22 @@ AnnotRichMedia::Content::Content(Dict *dict) { + if (obj1.isDict()) { + Object obj2 = obj1.getDict()->lookup("Names"); + if (obj2.isArray()) { +- nAssets = obj2.arrayGetLength() / 2; ++ const int length = obj2.arrayGetLength() / 2; + +- assets = (Asset **)gmallocn(nAssets, sizeof(Asset *)); ++ assets = (Asset **)gmallocn(length, sizeof(Asset *)); ++ for (int i = 0; i < length; ++i) { ++ Object objKey = obj2.arrayGet(2 * i); ++ Object objVal = obj2.arrayGet(2 * i + 1); + +- int counter = 0; +- for (int i = 0; i < nAssets; ++i) { +- assets[counter] = new AnnotRichMedia::Asset; +- +- Object objKey = obj2.arrayGet(i * 2); +- assets[counter]->fileSpec = obj2.arrayGet(i * 2 + 1); +- +- assets[counter]->name = new GooString( objKey.getString() ); +- ++counter; ++ if (!objKey.isString() || objVal.isNull()) { ++ error(errSyntaxError, -1, "Bad Annot Asset"); ++ continue; ++ } + ++ assets[nAssets] = new AnnotRichMedia::Asset; ++ assets[nAssets]->name = new GooString( objKey.getString() ); ++ assets[nAssets]->fileSpec = std::move(objVal); ++ ++nAssets; + } + } + } +-- +2.20.1 + diff --git a/SOURCES/poppler-0.66.0-stack-overflow.patch b/SOURCES/poppler-0.66.0-stack-overflow.patch new file mode 100644 index 0000000..1f6d53f --- /dev/null +++ b/SOURCES/poppler-0.66.0-stack-overflow.patch @@ -0,0 +1,20 @@ +From fada09a2ccc11a3a1d308e810f1336d8df6011fd Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Mon, 18 Mar 2019 00:50:00 +0100 +Subject: pdfunite: Fix stack overflow on broken file + +Fixes issue #741 + +diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc +index 26842f84..ab4abcad 100644 +--- a/poppler/PDFDoc.cc ++++ b/poppler/PDFDoc.cc +@@ -1703,7 +1703,7 @@ void PDFDoc::markObject (Object* obj, XRef *xRef, XRef *countRef, unsigned int n + array = obj->getArray(); + for (int i=0; igetLength(); i++) { + Object obj1 = array->getNF(i); +- markObject(&obj1, xRef, countRef, numOffset, oldRefNum, newRefNum); ++ markObject(&obj1, xRef, countRef, numOffset, oldRefNum, newRefNum, alreadyMarkedDicts); + } + break; + case objDict: diff --git a/SOURCES/poppler-0.66.0-stream-check.patch b/SOURCES/poppler-0.66.0-stream-check.patch new file mode 100644 index 0000000..3a4ba07 --- /dev/null +++ b/SOURCES/poppler-0.66.0-stream-check.patch @@ -0,0 +1,28 @@ +From 6912e06d9ab19ba28991b5cab3319d61d856bd6d Mon Sep 17 00:00:00 2001 +From: Adam Reichold +Date: Tue, 6 Nov 2018 09:00:02 +0100 +Subject: [PATCH] Check for stream before calling stream methods when saving an + embedded file. + +Closes #659 +--- + poppler/FileSpec.cc | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/poppler/FileSpec.cc b/poppler/FileSpec.cc +index 7479c2d2..d5543041 100644 +--- a/poppler/FileSpec.cc ++++ b/poppler/FileSpec.cc +@@ -93,6 +93,9 @@ bool EmbFile::save(const char *path) { + GBool EmbFile::save2(FILE *f) { + int c; + ++ if (unlikely(!m_objStr.isStream())) ++ return false; ++ + m_objStr.streamReset(); + while ((c = m_objStr.streamGetChar()) != EOF) { + fputc(c, f); +-- +2.19.1 + diff --git a/SOURCES/poppler-0.66.0-tiling-patterns.patch b/SOURCES/poppler-0.66.0-tiling-patterns.patch new file mode 100644 index 0000000..ea17a49 --- /dev/null +++ b/SOURCES/poppler-0.66.0-tiling-patterns.patch @@ -0,0 +1,47 @@ +From 718d428984e3a84fda521c0f5e6d975c7390af2b Mon Sep 17 00:00:00 2001 +From: Marek Kasik +Date: Fri, 6 Apr 2018 15:06:46 +0200 +Subject: [PATCH] cairo: Fix tiling patterns when pattern cell is too far + +Rendering of tiling pattern which has pattern matrix moving pattern cell +far away can fail on allocation of memory. This commit solves the issue by +modifying of cairo pattern matrix so that its offset is closer to the path +filled by the pattern. + +https://bugs.freedesktop.org/show_bug.cgi?id=105905 +--- + poppler/CairoOutputDev.cc | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc +index 631ab27b..b2e730bf 100644 +--- a/poppler/CairoOutputDev.cc ++++ b/poppler/CairoOutputDev.cc +@@ -915,6 +915,8 @@ GBool CairoOutputDev::tilingPatternFill(GfxState *state, Gfx *gfxA, Catalog *cat + StrokePathClip *strokePathTmp; + GBool adjusted_stroke_width_tmp; + cairo_pattern_t *maskTmp; ++ double xoffset, yoffset; ++ double det; + + width = bbox[2] - bbox[0]; + height = bbox[3] - bbox[1]; +@@ -976,6 +978,15 @@ GBool CairoOutputDev::tilingPatternFill(GfxState *state, Gfx *gfxA, Catalog *cat + if (cairo_pattern_status (pattern)) + return gFalse; + ++ det = pmat[0] * pmat[3] - pmat[1] * pmat[2]; ++ if (fabs(det) < 0.000001) ++ return gFalse; ++ ++ xoffset = round ((pmat[3] * pmat[4] - pmat[2] * pmat[5]) / (xStep * det)); ++ yoffset = - round ((pmat[1] * pmat[4] - pmat[0] * pmat[5]) / (yStep * det)); ++ pattern_matrix.x0 -= xoffset * pattern_matrix.xx * xStep + yoffset * pattern_matrix.xy * yStep; ++ pattern_matrix.y0 -= xoffset * pattern_matrix.yx * xStep + yoffset * pattern_matrix.yy * yStep; ++ + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + cairo_rectangle (cairo, xMin, yMin, xMax - xMin, yMax - yMin); + +-- +2.14.3 + diff --git a/SOURCES/poppler-0.66.0-tilingpatternfill-crash.patch b/SOURCES/poppler-0.66.0-tilingpatternfill-crash.patch new file mode 100644 index 0000000..b85bcfe --- /dev/null +++ b/SOURCES/poppler-0.66.0-tilingpatternfill-crash.patch @@ -0,0 +1,28 @@ +From b224e2f5739fe61de9fa69955d016725b2a4b78d Mon Sep 17 00:00:00 2001 +From: Albert Astals Cid +Date: Mon, 15 Jul 2019 22:11:09 +0200 +Subject: [PATCH] SplashOutputDev::tilingPatternFill: Fix crash on broken file + +Issue #802 +--- + poppler/SplashOutputDev.cc | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc +index 544f132d..3d2befc2 100644 +--- a/poppler/SplashOutputDev.cc ++++ b/poppler/SplashOutputDev.cc +@@ -4581,6 +4581,10 @@ bool SplashOutputDev::tilingPatternFill(GfxState *state, Gfx *gfxA, Catalog *cat + surface_width = (int) ceil (fabs(kx)); + surface_height = (int) ceil (fabs(ky)); + // adjust repeat values to completely fill region ++ if (unlikely(surface_width == 0 || surface_height == 0)) { ++ state->setCTM(savedCTM[0], savedCTM[1], savedCTM[2], savedCTM[3], savedCTM[4], savedCTM[5]); ++ return gFalse; ++ } + repeatX = result_width / surface_width; + repeatY = result_height / surface_height; + if (surface_width * repeatX < result_width) +-- +2.24.1 + diff --git a/SOURCES/poppler-0.66.0-valid-embedded-file-name.patch b/SOURCES/poppler-0.66.0-valid-embedded-file-name.patch new file mode 100644 index 0000000..6f0a841 --- /dev/null +++ b/SOURCES/poppler-0.66.0-valid-embedded-file-name.patch @@ -0,0 +1,81 @@ +From d2f5d424ba8752f9a9e9dad410546ec1b46caa0a Mon Sep 17 00:00:00 2001 +From: Adam Reichold +Date: Tue, 6 Nov 2018 09:08:06 +0100 +Subject: [PATCH] pdfdetach: Check for valid file name of embedded file before + using it to determine save path. + +Closes #660 +--- + utils/pdfdetach.cc | 24 ++++++++++++++++++------ + 1 file changed, 18 insertions(+), 6 deletions(-) + +diff --git a/utils/pdfdetach.cc b/utils/pdfdetach.cc +index a8720c64..71fa8608 100644 +--- a/utils/pdfdetach.cc ++++ b/utils/pdfdetach.cc +@@ -191,14 +191,18 @@ int main(int argc, char *argv[]) { + fileSpec = static_cast(embeddedFiles->get(i)); + printf("%d: ", i+1); + s1 = fileSpec->getFileName(); +- if ((s1->getChar(0) & 0xff) == 0xfe && (s1->getChar(1) & 0xff) == 0xff) { ++ if (!s1) { ++ exitCode = 3; ++ goto err2; ++ } ++ if (s1->hasUnicodeMarker()) { + isUnicode = gTrue; + j = 2; + } else { + isUnicode = gFalse; + j = 0; + } +- while (j < fileSpec->getFileName()->getLength()) { ++ while (j < s1->getLength()) { + if (isUnicode) { + u = ((s1->getChar(j) & 0xff) << 8) | (s1->getChar(j+1) & 0xff); + j += 2; +@@ -228,14 +232,18 @@ int main(int argc, char *argv[]) { + p = path; + } + s1 = fileSpec->getFileName(); +- if ((s1->getChar(0) & 0xff) == 0xfe && (s1->getChar(1) & 0xff) == 0xff) { ++ if (!s1) { ++ exitCode = 3; ++ goto err2; ++ } ++ if (s1->hasUnicodeMarker()) { + isUnicode = gTrue; + j = 2; + } else { + isUnicode = gFalse; + j = 0; + } +- while (j < fileSpec->getFileName()->getLength()) { ++ while (j < s1->getLength()) { + if (isUnicode) { + u = ((s1->getChar(j) & 0xff) << 8) | (s1->getChar(j+1) & 0xff); + j += 2; +@@ -276,14 +284,18 @@ int main(int argc, char *argv[]) { + } else { + p = path; + s1 = fileSpec->getFileName(); +- if ((s1->getChar(0) & 0xff) == 0xfe && (s1->getChar(1) & 0xff) == 0xff) { ++ if (!s1) { ++ exitCode = 3; ++ goto err2; ++ } ++ if (s1->hasUnicodeMarker()) { + isUnicode = gTrue; + j = 2; + } else { + isUnicode = gFalse; + j = 0; + } +- while (j < fileSpec->getFileName()->getLength()) { ++ while (j < s1->getLength()) { + if (isUnicode) { + u = ((s1->getChar(j) & 0xff) << 8) | (s1->getChar(j+1) & 0xff); + j += 2; +-- +2.19.1 + diff --git a/SOURCES/poppler-0.66.0-valid-embedded-file.patch b/SOURCES/poppler-0.66.0-valid-embedded-file.patch new file mode 100644 index 0000000..1880a0d --- /dev/null +++ b/SOURCES/poppler-0.66.0-valid-embedded-file.patch @@ -0,0 +1,46 @@ +From 77a30e94d96220d7e22dff5b3f0a7f296f01b118 Mon Sep 17 00:00:00 2001 +From: Adam Reichold +Date: Tue, 6 Nov 2018 09:13:41 +0100 +Subject: [PATCH] pdfdetach: Check for valid embedded file before trying to + save it. + +Closes #661 +--- + utils/pdfdetach.cc | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/utils/pdfdetach.cc b/utils/pdfdetach.cc +index 846584a4..a8720c64 100644 +--- a/utils/pdfdetach.cc ++++ b/utils/pdfdetach.cc +@@ -251,7 +251,12 @@ int main(int argc, char *argv[]) { + } + *p = '\0'; + +- if (!fileSpec->getEmbeddedFile()->save(path)) { ++ auto *embFile = fileSpec->getEmbeddedFile(); ++ if (!embFile || !embFile->isOk()) { ++ exitCode = 3; ++ goto err2; ++ } ++ if (!embFile->save(path)) { + error(errIO, -1, "Error saving embedded file as '{0:s}'", p); + exitCode = 2; + goto err2; +@@ -296,7 +301,12 @@ int main(int argc, char *argv[]) { + p = path; + } + +- if (!fileSpec->getEmbeddedFile()->save(p)) { ++ auto *embFile = fileSpec->getEmbeddedFile(); ++ if (!embFile || !embFile->isOk()) { ++ exitCode = 3; ++ goto err2; ++ } ++ if (!embFile->save(p)) { + error(errIO, -1, "Error saving embedded file as '{0:s}'", p); + exitCode = 2; + goto err2; +-- +2.19.1 + diff --git a/SPECS/poppler.spec b/SPECS/poppler.spec new file mode 100644 index 0000000..dded89b --- /dev/null +++ b/SPECS/poppler.spec @@ -0,0 +1,1120 @@ +%global test_sha 0d2bfd4af4c76a3bac27ccaff793d9129df7b57a +%global test_date 2009-05-13 + +Summary: PDF rendering library +Name: poppler +Version: 0.66.0 +Release: 27%{?dist} +License: (GPLv2 or GPLv3) and GPLv2+ and LGPLv2+ and MIT +URL: http://poppler.freedesktop.org/ +Source0: http://poppler.freedesktop.org/poppler-%{version}.tar.xz +# git archive --prefix test/ +Source1: %{name}-test-%{test_date}_%{test_sha}.tar.xz + +# https://bugzilla.redhat.com/show_bug.cgi?id=1185007 +Patch0: poppler-0.30.0-rotated-words-selection.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1580849 +Patch2: poppler-0.62.0-python3.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1602838 +Patch3: poppler-0.66.0-negative-object-number.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1602662 +# https://bugzilla.redhat.com/show_bug.cgi?id=1638712 +Patch4: poppler-0.66.0-covscan.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1626623 +Patch5: poppler-0.66.0-cycles-in-pdf-parsing.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1649457 +Patch6: poppler-0.66.0-embedded-file-check.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1649435 +Patch7: poppler-0.66.0-stream-check.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1649440 +Patch8: poppler-0.66.0-valid-embedded-file.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1649450 +Patch9: poppler-0.66.0-valid-embedded-file-name.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1644094 +Patch10: poppler-0.66.0-tiling-patterns.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1646546 +Patch11: poppler-0.66.0-display-profile.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1665266 +Patch12: poppler-0.66.0-dummy-xref-entry.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1672419 +Patch13: poppler-0.66.0-negative-xref-indices.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1665259 +Patch14: poppler-0.66.0-rich-media-annotation.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1665263 +Patch15: poppler-0.66.0-filespec.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1665273 +Patch16: poppler-0.66.0-check-catalog-is-dict.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1683632 +Patch17: poppler-0.66.0-image-stream-getline.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1686802 +Patch18: poppler-0.66.0-coverage-values.patch +Patch19: poppler-0.66.0-rescale-filter.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1691724 +Patch20: poppler-0.66.0-stack-overflow.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1618766 +Patch21: poppler-0.66.0-nss.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1713582 +Patch22: poppler-0.66.0-jpeg2000-component-size.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1732340 +Patch23: poppler-0.66.0-JPXStream-length.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1696636 +Patch24: poppler-0.66.0-PSOutputDev-rgb.patch + +# https://bugzilla.redhat.com/show_bug.cgi?id=1797453 +Patch25: poppler-0.66.0-tilingpatternfill-crash.patch + +BuildRequires: cmake +BuildRequires: gettext-devel +BuildRequires: pkgconfig(cairo) +BuildRequires: pkgconfig(cairo-ft) +BuildRequires: pkgconfig(cairo-pdf) +BuildRequires: pkgconfig(cairo-ps) +BuildRequires: pkgconfig(cairo-svg) +BuildRequires: pkgconfig(fontconfig) +BuildRequires: pkgconfig(freetype2) +BuildRequires: pkgconfig(gdk-pixbuf-2.0) +BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(gobject-2.0) +BuildRequires: pkgconfig(gobject-introspection-1.0) +BuildRequires: pkgconfig(gtk+-3.0) +BuildRequires: pkgconfig(gtk-doc) +BuildRequires: pkgconfig(lcms2) +BuildRequires: pkgconfig(libjpeg) +BuildRequires: pkgconfig(libopenjp2) +BuildRequires: pkgconfig(libpng) +BuildRequires: pkgconfig(libtiff-4) +BuildRequires: pkgconfig(nss) +BuildRequires: pkgconfig(poppler-data) +BuildRequires: pkgconfig(Qt5Core) +BuildRequires: pkgconfig(Qt5Gui) +BuildRequires: pkgconfig(Qt5Test) +BuildRequires: pkgconfig(Qt5Widgets) +BuildRequires: pkgconfig(Qt5Xml) +BuildRequires: python3-devel + +Requires: poppler-data + +Obsoletes: poppler-glib-demos < 0.60.1-1 + +%description +%{name} is a PDF rendering library. + +%package devel +Summary: Libraries and headers for poppler +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +You should install the poppler-devel package if you would like to +compile applications based on poppler. + +%package glib +Summary: Glib wrapper for poppler +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description glib +%{summary}. + +%package glib-devel +Summary: Development files for glib wrapper +Requires: %{name}-glib%{?_isa} = %{version}-%{release} +Requires: %{name}-devel%{?_isa} = %{version}-%{release} +Suggests: %{name}-doc = %{version}-%{release} + +%description glib-devel +%{summary}. + +%package glib-doc +Summary: Documentation for glib wrapper +BuildArch: noarch + +%description glib-doc +%{summary}. + +%package qt5 +Summary: Qt5 wrapper for poppler +Requires: %{name}%{?_isa} = %{version}-%{release} +%description qt5 +%{summary}. + +%package qt5-devel +Summary: Development files for Qt5 wrapper +Requires: %{name}-qt5%{?_isa} = %{version}-%{release} +Requires: %{name}-devel%{?_isa} = %{version}-%{release} +Requires: qt5-qtbase-devel +%description qt5-devel +%{summary}. + +%package cpp +Summary: Pure C++ wrapper for poppler +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description cpp +%{summary}. + +%package cpp-devel +Summary: Development files for C++ wrapper +Requires: %{name}-cpp%{?_isa} = %{version}-%{release} +Requires: %{name}-devel%{?_isa} = %{version}-%{release} + +%description cpp-devel +%{summary}. + +%package utils +Summary: Command line utilities for converting PDF files +Requires: %{name}%{?_isa} = %{version}-%{release} +%description utils +Command line tools for manipulating PDF files and converting them to +other formats. + +%prep +%autosetup -p1 -b 1 + +%build +mkdir build +cd build +export CC="gcc -fPIC" # hack to make the cmake call pass +%cmake \ + -DENABLE_CMS=lcms2 \ + -DENABLE_DCTDECODER=libjpeg \ + -DENABLE_GTK_DOC=ON \ + -DENABLE_LIBOPENJPEG=openjpeg2 \ + -DENABLE_XPDF_HEADERS=ON \ + -DENABLE_ZLIB=OFF \ + -DENABLE_NSS=ON \ + .. +unset CC +make %{?_smp_mflags} + +%install +cd build +make install DESTDIR=$RPM_BUILD_ROOT + +%check +make %{?_smp_mflags} test + +# verify pkg-config sanity/version +export PKG_CONFIG_PATH=%{buildroot}%{_datadir}/pkgconfig:%{buildroot}%{_libdir}/pkgconfig +test "$(pkg-config --modversion poppler)" = "%{version}" +test "$(pkg-config --modversion poppler-cairo)" = "%{version}" +test "$(pkg-config --modversion poppler-cpp)" = "%{version}" +test "$(pkg-config --modversion poppler-glib)" = "%{version}" +test "$(pkg-config --modversion poppler-qt5)" = "%{version}" +test "$(pkg-config --modversion poppler-splash)" = "%{version}" + +%post -p /sbin/ldconfig +%postun -p /sbin/ldconfig + +%post glib -p /sbin/ldconfig +%postun glib -p /sbin/ldconfig + +%post qt5 -p /sbin/ldconfig +%postun qt5 -p /sbin/ldconfig + +%post cpp -p /sbin/ldconfig +%postun cpp -p /sbin/ldconfig + +%files +%doc README +%license COPYING +%{_libdir}/libpoppler.so.78* + +%files devel +%{_libdir}/pkgconfig/poppler.pc +%{_libdir}/pkgconfig/poppler-splash.pc +%{_libdir}/libpoppler.so +%dir %{_includedir}/poppler/ +# xpdf headers +%{_includedir}/poppler/*.h +%{_includedir}/poppler/fofi/ +%{_includedir}/poppler/goo/ +%{_includedir}/poppler/splash/ + +%files glib +%{_libdir}/libpoppler-glib.so.8* +%{_libdir}/girepository-1.0/Poppler-0.18.typelib + +%files glib-devel +%{_libdir}/pkgconfig/poppler-glib.pc +%{_libdir}/pkgconfig/poppler-cairo.pc +%{_libdir}/libpoppler-glib.so +%{_datadir}/gir-1.0/Poppler-0.18.gir +%{_includedir}/poppler/glib/ + +%files glib-doc +%license COPYING +%{_datadir}/gtk-doc/ + +%files qt5 +%{_libdir}/libpoppler-qt5.so.1* + +%files qt5-devel +%{_libdir}/libpoppler-qt5.so +%{_libdir}/pkgconfig/poppler-qt5.pc +%{_includedir}/poppler/qt5/ + +%files cpp +%{_libdir}/libpoppler-cpp.so.0* + +%files cpp-devel +%{_libdir}/pkgconfig/poppler-cpp.pc +%{_libdir}/libpoppler-cpp.so +%{_includedir}/poppler/cpp + +%files utils +%{_bindir}/pdf* +%{_mandir}/man1/* + +%changelog +* Mon Dec 14 2020 Owen Taylor - 0.66.0-27 +- Improve python3 build dependency +- Cherry-picked from rhel-8.4.0 branch (commit by Marek Kasik) + +* Thu Apr 16 2020 Marek Kasik - 0.66.0-27 +- Fix crash on broken file in tilingPatternFill() +- Resolves: #1801341 + +* Tue Aug 13 2019 Marek Kasik - 0.66.0-26 +- Coverity scan related fixes +- Related: #1618766 + +* Tue Aug 13 2019 Marek Kasik - 0.66.0-25 +- Check whether input is RGB in PSOutputDev::checkPageSlice() +- also when using "-optimizecolorspace" flag +- Resolves: #1697576 + +* Fri Aug 9 2019 Marek Kasik - 0.66.0-24 +- Check whether input is RGB in PSOutputDev::checkPageSlice() +- Resolves: #1697576 + +* Fri Aug 9 2019 Marek Kasik - 0.66.0-23 +- Ignore dict Length if it is broken +- Resolves: #1733027 + +* Fri Aug 9 2019 Marek Kasik - 0.66.0-22 +- Fail gracefully if not all components of JPEG2000Stream +- have the same size +- Resolves: #1723505 + +* Fri Jun 28 2019 Marek Kasik - 0.66.0-21 +- Implement crypto functions using NSS +- Resolves: #1618766 + +* Wed Apr 3 2019 Marek Kasik - 0.66.0-20 +- Fix stack overflow on broken file +- Resolves: #1691887 + +* Mon Apr 1 2019 Marek Kasik - 0.66.0-19 +- Constrain number of cycles in rescale filter +- Compute correct coverage values for box filter +- Resolves: #1688418 + +* Mon Apr 1 2019 Marek Kasik - 0.66.0-18 +- Fix possible crash on broken files in ImageStream::getLine() +- Resolves: #1685268 + +* Mon Apr 1 2019 Marek Kasik - 0.66.0-17 +- Check Catalog from XRef for being a Dict +- Resolves: #1677347 + +* Mon Apr 1 2019 Marek Kasik - 0.66.0-16 +- Move the fileSpec.dictLookup call inside fileSpec.isDict if +- Resolves: #1677028 + +* Mon Apr 1 2019 Marek Kasik - 0.66.0-15 +- Do not try to construct invalid rich media annotation assets +- Resolves: #1677025 + +* Mon Apr 1 2019 Marek Kasik - 0.66.0-14 +- Defend against requests for negative XRef indices +- Resolves: #1673699 + +* Mon Apr 1 2019 Marek Kasik - 0.66.0-13 +- Do not try to parse into unallocated XRef entry +- Resolves: #1677057 + +* Mon Apr 1 2019 Marek Kasik - 0.66.0-12 +- Avoid global display profile state becoming an uncontrolled +- memory leak +- Resolves: #1646552 + +* Fri Dec 14 2018 Marek Kasik - 0.66.0-11 +- Fix tiling patterns when pattern cell is too far +- Resolves: #1644094 + +* Fri Nov 16 2018 Marek Kasik - 0.66.0-10 +- Check for valid file name of embedded file +- Resolves: #1649453 + +* Fri Nov 16 2018 Marek Kasik - 0.66.0-9 +- Check for valid embedded file before trying to save it +- Resolves: #1649443 + +* Fri Nov 16 2018 Marek Kasik - 0.66.0-8 +- Check for stream before calling stream methods +- when saving an embedded file +- Resolves: #1649438 + +* Thu Nov 15 2018 Marek Kasik - 0.66.0-7 +- Fix crash on missing embedded file +- Resolves: #1649460 + +* Thu Nov 15 2018 Marek Kasik - 0.66.0-6 +- Avoid cycles in PDF parsing +- Resolves: #1626623 + +* Fri Oct 12 2018 Marek Kasik - 0.66.0-5 +- Fix crash when accessing list of selections +- Resolves: #1638712 + +* Mon Sep 24 2018 Marek Kasik - 0.66.0-4 +- Fix important issues found by covscan +- Resolves: #1602662 + +* Tue Aug 14 2018 Petr Viktorin - 0.66.0-3 +- Fix BuildRequires for /usr/bin/python3 +- Resolves: #1615561 + +* Thu Jul 26 2018 Marek Kasik - 0.66.0-2 +- Fix crash when Object has negative number (CVE-2018-13988) +- Resolves: #1607463 + +* Thu Jul 12 2018 Marek Kasik - 0.66.0-1 +- Rebase poppler to 0.66.0 +- Resolves: #1600553 + +* Mon Jun 11 2018 Marek Kasik - 0.62.0-4 +- Drop reversion of removal of Qt4 frontend + +* Fri May 25 2018 Marek Kasik - 0.62.0-3 +- Fix infinite recursion (CVE-2017-18267) +- Resolves: #1578779 + +* Thu May 24 2018 Marek Kasik - 0.62.0-2 +- Fix building of poppler with python3 only +- Resolves: #1580849 + +* Wed Feb 14 2018 David Tardon - 0.62.0-1 +- new upstream release + +* Fri Feb 09 2018 Fedora Release Engineering - 0.61.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Tue Nov 14 2017 David Tardon - 0.61.1-1 +- new upstream release + +* Mon Nov 06 2017 David Tardon - 0.61.0-1 +- new upstream release + +* Tue Oct 24 2017 Rex Dieter - 0.60.1-2 +- -qt5: drop hard-coded versioned dependency + +* Wed Oct 04 2017 David Tardon - 0.60.0-1 +- new upstream release + +* Mon Sep 25 2017 Caolán McNamara - 0.59.0-2 +- Resolves: rhbz#1494583 CVE-2017-14520 + +* Mon Sep 04 2017 David Tardon - 0.59.0-1 +- new upstream release + +* Thu Aug 03 2017 David Tardon - 0.57.0-1 +- new upstream release + +* Thu Aug 03 2017 Fedora Release Engineering - 0.56.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 0.56.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Wed Jul 12 2017 Caolán McNamara - 0.56.0-2 +- Resolves: rhbz#1459067 CVE-2017-7515 CVE-2017-9775 CVE-2017-9776 CVE-2017-9865 + +* Fri Jun 23 2017 David Tardon - 0.56.0-1 +- new upstream release + +* Tue May 30 2017 Caolán McNamara - 0.55.0-2 +- Resolves: rhbz#1456828 CVE-2017-7511 Null pointer deference + +* Tue May 23 2017 David Tardon - 0.55.0-1 +- new upstream release + +* Mon Mar 20 2017 David Tardon - 0.53.0-1 +- new upstream release + +* Fri Feb 17 2017 David Tardon - 0.52.0-1 +- new upstream release + +* Sat Feb 11 2017 Fedora Release Engineering - 0.51.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Mon Jan 16 2017 Caolán McNamara - 0.51.0-1 +- new upstream release + +* Fri Dec 16 2016 David Tardon - 0.50.0-1 +- new upstream release + +* Tue Nov 22 2016 David Tardon - 0.49.0-1 +- new upstream release + +* Fri Oct 21 2016 Marek Kasik - 0.48.0-1 +- Update to 0.48.0 +- Resolves: #1359555 + +* Mon Sep 26 2016 Marek Kasik - 0.45.0-2 +- Don't crash when calling cmsGetColorSpace() +- Resolves: #1363669 + +* Mon Jul 18 2016 Marek Kasik - 0.45.0-1 +- Update to 0.45.0 +- Resolves: #1338421 + +* Mon Jul 11 2016 Marek Kasik - 0.43.0-2 +- Restore the current position of char also in output device +- Related: #1352717 + +* Tue May 3 2016 Marek Kasik - 0.43.0-1 +- Update to 0.43.0 +- Resolves: #1318462 + +* Fri Feb 26 2016 Marek Kasik - 0.41.0-1 +- Update to 0.41.0 +- Resolves: #1309145 + +* Thu Feb 04 2016 Fedora Release Engineering - 0.40.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Fri Jan 22 2016 Marek Kasik - 0.40.0-1 +- Update to 0.40.0 +- Resolves: #1251781 + +* Wed Jul 22 2015 Marek Kasik - 0.34.0-1 +- Update to 0.34.0 +- Resolves: #1241305 + +* Thu Jun 18 2015 Fedora Release Engineering - 0.33.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Fri Jun 5 2015 Marek Kasik - 0.33.0-1 +- Update to 0.33.0 +- Resolves: #1190427 + +* Sat May 02 2015 Kalev Lember - 0.30.0-5 +- Rebuilt for GCC 5 C++11 ABI change + +* Thu Mar 26 2015 Marek Kasik - 0.30.0-4 +- Respect orientation when selecting words +- Resolves: #1185007 + +* Sat Feb 21 2015 Till Maas - 0.30.0-3 +- Rebuilt for Fedora 23 Change + https://fedoraproject.org/wiki/Changes/Harden_all_packages_with_position-independent_code + +* Fri Jan 23 2015 Marek Kasik - 0.30.0-2 +- Use libopenjpeg2 instead of libopenjpeg + +* Fri Jan 23 2015 Marek Kasik - 0.30.0-1 +- Update to 0.30.0 +- Resolves: #1171056 + +* Tue Jan 20 2015 Marek Kasik - 0.28.1-3 +- Revert previous commit (It needs poppler-0.30.0) + +* Tue Jan 20 2015 Marek Kasik - 0.28.1-2 +- Use libopenjpeg2 instead of libopenjpeg + +* Fri Nov 14 2014 Marek Kasik - 0.28.1-1 +- Update to 0.28.1 +- Resolves: #1147443 + +* Wed Aug 27 2014 Marek Kasik - 0.26.4-1 +- Update to 0.26.4 + +* Sun Aug 17 2014 Fedora Release Engineering - 0.26.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Wed Jul 30 2014 Marek Kasik - 0.26.3-1 +- Update to 0.26.3 + +* Tue Jul 22 2014 Kalev Lember - 0.26.2-2 +- Rebuilt for gobject-introspection 1.41.4 + +* Fri Jun 27 2014 Marek Kasik - 0.26.2-1 +- Update to 0.26.2 + +* Sat Jun 07 2014 Fedora Release Engineering - 0.26.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue May 13 2014 Marek Kasik - 0.26.0-1 +- Update to 0.26.0 + +* Fri Jan 3 2014 Marek Kasik - 0.24.3-3 +- Use correct format string +- Resolves: #1048202 + +* Mon Nov 11 2013 Rex Dieter 0.24.3-2 +- rebuild (qt5 qreal/arm) + +* Tue Oct 29 2013 Marek Kasik - 0.24.3-1 +- Update to 0.24.3 +- Resolves: #1023712 + +* Fri Oct 18 2013 Rex Dieter - 0.24.2-4 +- fix mocversiongrep configure checks (so Qt 5.2 works) +- %%configure --disable-silent-rules + +* Fri Oct 18 2013 Rex Dieter 0.24.2-3 +- undo ExcludeArch: ppc ppc64 (qt5-qtbase-5.1.1-6+ fixed) + +* Thu Oct 17 2013 Rex Dieter 0.24.2-2 +- -qt5: ExcludeArch: ppc ppc64 (f20, hopefully temporary) + +* Mon Sep 30 2013 Marek Kasik - 0.24.2-1 +- Update to 0.24.2 + +* Mon Sep 30 2013 Marek Kasik - 0.24.1-2 +- Don't convert pdftohtml.1 to UTF-8, it is already UTF-8 + +* Tue Aug 27 2013 Marek Kasik - 0.24.1-1 +- Update to 0.24.1 + +* Tue Aug 20 2013 Marek Kasik - 0.24.0-2 +- Fix Qt5 requirements + +* Mon Aug 19 2013 Marek Kasik - 0.24.0-1 +- Update to 0.24.0 + +* Sun Aug 04 2013 Fedora Release Engineering - 0.22.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* Mon Jun 24 2013 Marek Kasik 0.22.5-1 +- Update to 0.22.5 + +* Thu Jun 20 2013 Marek Kasik 0.22.1-5 +- Switch from LCMS to LCMS2 +- Resolves: #975465 + +* Wed Jun 5 2013 Marek Kasik 0.22.1-4 +- Fix changelog dates + +* Fri Apr 12 2013 Marek Kasik 0.22.1-3 +- Enable generating of TIFF files by pdftoppm + +* Thu Apr 11 2013 Marek Kasik 0.22.1-2 +- Fix man pages of pdftops and pdfseparate + +* Wed Feb 27 2013 Marek Kasik 0.22.1-1 +- Update to 0.22.1 + +* Thu Feb 14 2013 Fedora Release Engineering - 0.22.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Sun Jan 20 2013 Rex Dieter 0.22.0-2 +- -demos: omit extraneous (and broken) dep + +* Fri Jan 18 2013 Marek Kasik 0.22.0-1 +- Update to 0.22.0 + +* Tue Nov 13 2012 Marek Kasik 0.20.2-9 +- Move poppler-glib-demo to new sub-package demos +- Resolves: #872338 + +* Mon Nov 12 2012 Marek Kasik 0.20.2-8 +- Add references to corresponding bugs for poppler-0.20.3-5.patch + +* Tue Nov 6 2012 Marek Kasik 0.20.2-7 +- Add missing hunk to patch poppler-0.20.3-5.patch + +* Tue Nov 6 2012 Marek Kasik 0.20.2-6 +- Backport most of the changes from poppler-0.20.3 - poppler-0.20.5 +- (those which doesn't change API or ABI and are important) +- See poppler-0.20.3-5.patch for detailed list of included commits + +* Wed Oct 31 2012 Marek Kasik 0.20.2-5 +- Remove unused patch + +* Wed Oct 31 2012 Marek Kasik 0.20.2-4 +- Update License field + +* Mon Aug 6 2012 Marek Kasik 0.20.2-3 +- Fix conversion to ps when having multiple strips + +* Mon Aug 6 2012 Marek Kasik 0.20.2-2 +- Make sure xScale and yScale are always initialized +- Resolves: #840515 + +* Mon Aug 6 2012 Marek Kasik 0.20.2-1 +- Update to 0.20.2 + +* Mon Aug 6 2012 Marek Kasik 0.20.1-3 +- Try empty string instead of NULL as password if needed +- Resolves: #845578 + +* Sat Jul 21 2012 Fedora Release Engineering - 0.20.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Mon Jul 2 2012 Marek Kasik 0.20.1-1 +- Update to 0.20.1 + +* Mon Jun 25 2012 Nils Philippsen +- license is "GPLv2 or GPLv3" from poppler-0.20.0 on (based off xpdf-3.03) + +* Wed May 16 2012 Marek Kasik 0.20.0-1 +- Update to 0.20.0 + +* Fri May 4 2012 Marek Kasik 0.18.4-3 +- Backport of a patch which sets mask matrix before drawing an image with a mask +- Resolves: #817378 + +* Tue Feb 28 2012 Fedora Release Engineering - 0.18.4-2 +- Rebuilt for c++ ABI breakage + +* Sat Feb 18 2012 Rex Dieter 0.18.4-1 +- 0.18.4 + +* Thu Feb 09 2012 Rex Dieter 0.18.3-3 +- rebuild (openjpeg) + +* Tue Jan 17 2012 Rex Dieter 0.18.3-2 +- -devel: don't own all headers + +* Mon Jan 16 2012 Rex Dieter 0.18.3-1 +- 0.18.3 + +* Sat Jan 14 2012 Fedora Release Engineering - 0.18.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Tue Dec 06 2011 Marek Kasik - 0.18.2-1 +- Update to 0.18.2 +- Remove upstreamed patches + +* Mon Dec 05 2011 Adam Jackson 0.18.1-3 +- Rebuild for new libpng + +* Fri Oct 28 2011 Rex Dieter 0.18.1-2 +- poppler-glib.pc pkgconfig file broken (#749898) +- %%check: verify pkgconfig sanity + +* Fri Oct 28 2011 Rex Dieter 0.18.1-1 +- Update to 0.18.1 +- pkgconfig-style deps +- tighten deps with %%_isa + +* Fri Sep 30 2011 Marek Kasik - 0.18.0-2 +- rebuild + +* Fri Sep 30 2011 Marek Kasik - 0.18.0-1 +- Update to 0.18.0 + +* Mon Sep 26 2011 Marek Kasik - 0.17.3-2 +- Don't include pdfextract and pdfmerge in resulting packages for now +- since they conflict with packages pdfmerge and mupdf (#740906) + +* Mon Sep 19 2011 Marek Kasik - 0.17.3-1 +- Update to 0.17.3 + +* Wed Aug 17 2011 Marek Kasik - 0.17.0-2 +- Fix a problem with freeing of memory in PreScanOutputDev (#730941) + +* Fri Jul 15 2011 Marek Kasik - 0.17.0-1 +- Update to 0.17.0 + +* Thu Jun 30 2011 Rex Dieter 0.16.7-1 +- 0.16.7 + +* Wed Jun 22 2011 Marek Kasik - 0.16.6-2 +- Drop dependency on gtk-doc (#604412) + +* Thu Jun 2 2011 Marek Kasik - 0.16.6-1 +- Update to 0.16.6 + +* Thu May 5 2011 Marek Kasik - 0.16.5-1 +- Update to 0.16.5 + +* Thu Mar 31 2011 Marek Kasik - 0.16.4-1 +- Update to 0.16.4 + +* Sun Mar 13 2011 Marek Kasik - 0.16.3-2 +- Update to 0.16.3 + +* Sun Mar 13 2011 Marek Kasik - 0.16.3-1 +- Update to 0.16.3 + +* Wed Feb 09 2011 Fedora Release Engineering - 0.16.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Feb 2 2011 Marek Kasik - 0.16.2-1 +- Update to 0.16.2 + +* Tue Jan 18 2011 Rex Dieter - 0.16.0-3 +- drop qt3 bindings +- rename -qt4 -> -qt + +* Wed Jan 12 2011 Rex Dieter - 0.16.0-2 +- rebuild (openjpeg) + +* Mon Dec 27 2010 Rex Dieter - 0.16.0-1 +- 0.16.0 + +* Fri Dec 10 2010 Marek Kasik - 0.15.3-1 +- Update to 0.15.3 + +* Mon Nov 1 2010 Marek Kasik - 0.15.1-1 +- Update to 0.15.1 +- Remove CVE-2010-3702, 3703 and 3704 patches (they are already in 0.15.1) + +* Thu Oct 7 2010 Marek Kasik - 0.15.0-5 +- Add poppler-0.15.0-CVE-2010-3702.patch + (Properly initialize parser) +- Add poppler-0.15.0-CVE-2010-3703.patch + (Properly initialize stack) +- Add poppler-0.15.0-CVE-2010-3704.patch + (Fix crash in broken pdf (code < 0)) +- Resolves: #639861 + +* Wed Sep 29 2010 jkeating - 0.15.0-4 +- Rebuilt for gcc bug 634757 + +* Mon Sep 27 2010 Marek Kasik - 0.15.0-3 +- Remove explicit requirement of gobject-introspection + +* Fri Sep 24 2010 Marek Kasik - 0.15.0-2 +- Move requirement of gobject-introspection to glib sub-package + +* Fri Sep 24 2010 Marek Kasik - 0.15.0-1 +- Update to 0.15.0 +- Enable introspection + +* Sat Sep 11 2010 Rex Dieter - 0.14.3-1 +- Update to 0.14.3 + +* Thu Aug 19 2010 Marek Kasik - 0.14.2-1 +- Update to 0.14.2 +- Remove poppler-0.12.1-objstream.patch + +* Fri Jul 16 2010 Marek Kasik - 0.14.1-1 +- Update to 0.14.1 +- Don't apply poppler-0.12.1-objstream.patch, it is not needed anymore + +* Fri Jun 18 2010 Matthias Clasen - 0.14.0-1 +- Update to 0.14.0 + +* Wed May 26 2010 Marek Kasik - 0.13.4-1 +- poppler-0.13.4 + +* Mon May 3 2010 Marek Kasik - 0.13.3-2 +- Update "sources" file +- Add BuildRequires "gettext-devel" + +* Fri Apr 30 2010 Marek Kasik - 0.13.3-1 +- poppler-0.13.3 + +* Thu Mar 4 2010 Marek Kasik - 0.12.4-2 +- Fix showing of radio buttons (#480868) + +* Thu Feb 18 2010 Rex Dieter - 0.12.4-1 +- popper-0.12.4 + +* Tue Feb 16 2010 Marek Kasik - 0.12.3-9 +- Fix downscaling of rotated pages (#563353) + +* Thu Jan 28 2010 Marek Kasik - 0.12.3-8 +- Get current FcConfig before using it (#533992) + +* Sun Jan 24 2010 Rex Dieter - 0.12.3-7 +- use alternative/upstream downscale patch (#556549, fdo#5589) + +* Wed Jan 20 2010 Marek Kasik - 0.12.3-6 +- Add dependency on poppler-data (#553991) + +* Tue Jan 19 2010 Rex Dieter - 0.12.3-5 +- cairo backend, scale images correctly (#556549, fdo#5589) + +* Fri Jan 15 2010 Rex Dieter - 0.12.3-4 +- Sanitize versioned Obsoletes/Provides + +* Fri Jan 15 2010 Marek Kasik - 0.12.3-3 +- Correct permissions of goo/GooTimer.h +- Convert pdftohtml.1 to utf8 +- Make the pdftohtml's Provides/Obsoletes versioned + +* Thu Jan 07 2010 Rex Dieter - 0.12.3-1 +- poppler-0.12.3 + +* Mon Nov 23 2009 Rex Dieter - 0.12.2-1 +- poppler-0.12.2 + +* Sun Oct 25 2009 Rex Dieter - 0.12.1-3 +- CVE-2009-3607 poppler: create_surface_from_thumbnail_data + integer overflow (#526924) + +* Mon Oct 19 2009 Rex Dieter - 0.12.1-1 +- poppler-0.12.1 +- deprecate xpdf/pdftohtml Conflicts/Obsoletes + +* Wed Sep 09 2009 Rex Dieter - 0.12.0-1 +- Update to 0.12.0 + +* Tue Aug 18 2009 Rex Dieter - 0.11.3-1 +- Update to 0.11.3 + +* Mon Aug 3 2009 Matthias Clasen - 0.11.2-1 +- Update to 0.11.2 + +* Sun Jul 26 2009 Fedora Release Engineering - 0.11.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue Jun 23 2009 Rex Dieter - 0.11.1-2 +- omit poppler-data (#507675) + +* Tue Jun 23 2009 Rex Dieter - 0.11.1-1 +- poppler-0.11.1 + +* Mon Jun 22 2009 Rex Dieter - 0.11.0-6 +- reduce lib deps in qt/qt4 pkg-config support + +* Sat Jun 20 2009 Rex Dieter - 0.11.0-5 +- --enable-libjpeg +- (explicitly) --disable-zlib + +* Fri Jun 19 2009 Rex Dieter - 0.11.0-3 +- --enable-libopenjpeg, --disable-zlib + +* Sun May 24 2009 Rex Dieter - 0.11.0-2 +- update changelog +- track sonames + +* Tue May 19 2009 Bastien Nocera - 0.11.0-1 +- Update to 0.11.0 + +* Thu Mar 12 2009 Matthias Clasen - 0.10.5-1 +- Update to 0.10.5 + +* Thu Feb 26 2009 Fedora Release Engineering - 0.10.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Tue Feb 17 2009 Matthias Clasen - 0.10.4-1 +- Update to 0.10.4 + +* Tue Jan 20 2009 Rex Dieter - 0.10.3-2 +- add needed scriptlets +- nuke rpaths + +* Tue Jan 13 2009 Matthias Clasen - 0.10.3-1 +- Update to 0.10.3 + +* Wed Dec 17 2008 Matthias Clasen - 0.10.2-1 +- Update to 0.10.2 + +* Tue Nov 11 2008 Matthias Clasen - 0.10.1-1 +- Update to 0.10.1 and -data 0.2.1 + +* Tue Sep 16 2008 Rex Dieter - 0.8.7-2 +- cleanup qt3 hack +- %%description cosmetics + +* Sun Sep 7 2008 Matthias Clasen - 0.8.7-1 +- Update to 0.8.7 + +* Fri Aug 22 2008 Matthias Clasen - 0.8.6-1 +- Update to 0.8.6 + +* Tue Aug 05 2008 Colin Walters - 0.8.5-1 +- Update to 0.8.5 + +* Wed Jun 4 2008 Matthias Clasen - 0.8.3-1 +- Update to 0.8.3 + +* Mon Apr 28 2008 Matthias Clasen - 0.8.1-1 +- Update to 0.8.1 + +* Sun Apr 06 2008 Adam Jackson 0.8.0-3 +- poppler-0.8.0-ocg-crash.patch: Fix a crash when no optional content + groups are defined. +- Mangle configure to account for the new directory for qt3 libs. +- Fix grammar in %%description. + +* Tue Apr 01 2008 Rex Dieter - 0.8.0-2 +- -qt-devel: Requires: qt3-devel + +* Sun Mar 30 2008 Matthias Clasen - 0.8.0-1 +- Update to 0.8.0 + +* Sun Mar 23 2008 Matthias Clasen - 0.7.3-1 +- Update to 0.7.3 + +* Wed Mar 12 2008 Matthias Clasen - 0.7.2-1 +- Update to 0.7.2 + +* Thu Feb 28 2008 Matthias Clasen - 0.7.1-1 +- Update to 0.7.1 + +* Thu Feb 21 2008 Matthias Clasen - 0.7.0-1 +- Update to 0.7.0 + +* Tue Feb 19 2008 Fedora Release Engineering - 0.6.4-4 +- Autorebuild for GCC 4.3 + +* Mon Feb 18 2008 Jindrich Novy - 0.6.4-3 +- apply ObjStream patch (#433090) + +* Tue Jan 29 2008 Matthias Clasen - 0.6.4-2 +- Add some required inter-subpackge deps + +* Tue Jan 29 2008 Matthias Clasen - 0.6.4-1 +- Update to 0.6.4 +- Split off poppler-glib + +* Sun Dec 2 2007 Matthias Clasen - 0.6.2-3 +- Fix the qt3 checks some more + +* Wed Nov 28 2007 Matthias Clasen - 0.6.2-2 +- package xpdf headers in poppler-devel (Jindrich Novy) +- Fix qt3 detection (Denis Leroy) + +* Thu Nov 22 2007 Matthias Clasen - 0.6.2-1 +- Update to 0.6.2 + +* Thu Oct 11 2007 Rex Dieter - 0.6-2 +- include qt4 wrapper + +* Tue Sep 4 2007 Kristian Høgsberg - 0.6-1 +- Update to 0.6 + +* Wed Aug 15 2007 Matthias Clasen - 0.5.91-2 +- Remove debug spew + +* Tue Aug 14 2007 Matthias Clasen - 0.5.91-1 +- Update to 0.5.91 + +* Wed Aug 8 2007 Matthias Clasen - 0.5.9-2 +- Update the license field + +* Mon Jun 18 2007 Matthias Clasen - 0.5.9-1 +- Update to 0.5.9 + +* Thu Mar 1 2007 Bill Nottingham - 0.5.4-7 +- fix it so the qt pkgconfig/.so aren't in the main poppler-devel + +* Fri Dec 15 2006 Matthias Clasen - 0.5.4-5 +- Include epoch in the Provides/Obsoletes for xpdf-utils + +* Wed Dec 13 2006 Matthias Clasen - 0.5.4-4 +- Add Provides/Obsoletes for xpdf-utils (#219033) + +* Fri Dec 08 2006 Rex Dieter - 0.5.4-3 +- drop hard-wired: Req: gtk2 +- --disable-static +- enable qt wrapper +- -devel: Requires: pkgconfig + +* Sun Oct 01 2006 Jesse Keating - 0.5.4-2 +- rebuilt for unwind info generation, broken in gcc-4.1.1-21 + +* Thu Sep 21 2006 Kristian Høgsberg - 0.5.4-1.fc6 +- Rebase to 0.5.4, drop poppler-0.5.3-libs.patch, fixes #205813, + #205549, #200613, #172137, #172138, #161293 and more. + +* Wed Sep 13 2006 Kristian Høgsberg - 0.5.3-3.fc6 +- Move .so to -devel (#203637). + +* Mon Aug 14 2006 Matthias Clasen - 0.5.3-2.fc6 +- link against fontconfig (see bug 202256) + +* Wed Jul 12 2006 Jesse Keating - 0.5.3-1.1 +- rebuild + +* Wed May 31 2006 Kristian Høgsberg 0.5.3-1 +- Update to 0.5.3. + +* Mon May 22 2006 Kristian Høgsberg 0.5.2-1 +- Update to 0.5.2. + +* Wed Mar 1 2006 Kristian Høgsberg 0.5.1-2 +- Rebuild the get rid of old soname dependency. + +* Tue Feb 28 2006 Kristian Høgsberg 0.5.1-1 +- Update to version 0.5.1. + +* Fri Feb 10 2006 Jesse Keating - 0.5.0-4.2 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 0.5.0-4.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Wed Jan 18 2006 Ray Strode - 0.5.0-4 +- change xpdf conflict version to be <= instead of < + +* Wed Jan 18 2006 Ray Strode - 0.5.0-3 +- update conflicts: xpdf line to be versioned + +* Wed Jan 11 2006 Kristian Høgsberg - 0.5.0-2.0 +- Update to 0.5.0 and add poppler-utils subpackage. +- Flesh out poppler-utils subpackage. + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Sun Sep 4 2005 Kristian Høgsberg - 0.4.2-1 +- Update to 0.4.2 and disable splash backend so we don't build it. + +* Fri Aug 26 2005 Marco Pesenti Gritti - 0.4.1-2 +- Rebuild + +* Fri Aug 26 2005 Marco Pesenti Gritti - 0.4.1-1 +- Update to 0.4.1 + +* Wed Aug 17 2005 Kristian Høgsberg - 0.4.0-2 +- Bump release and rebuild. + +* Wed Aug 17 2005 Marco Pesenti gritti - 0.4.0-1 +- Update to 0.4.0 + +* Mon Aug 15 2005 Kristian Høgsberg - 0.3.3-2 +- Rebuild to pick up new cairo soname. + +* Mon Jun 20 2005 Kristian Høgsberg - 0.3.3-1 +- Update to 0.3.3 and change to build cairo backend. + +* Sun May 22 2005 Marco Pesenti gritti - 0.3.2-1 +- Update to 0.3.2 + +* Sat May 7 2005 Marco Pesenti Gritti - 0.3.1 +- Update to 0.3.1 + +* Sat Apr 23 2005 Marco Pesenti Gritti - 0.3.0 +- Update to 0.3.0 + +* Wed Apr 13 2005 Florian La Roche +- remove empty post/postun scripts + +* Wed Apr 6 2005 Marco Pesenti Gritti - 0.2.0-1 +- Update to 0.2.0 + +* Sat Mar 12 2005 Marco Pesenti Gritti - 0.1.2-1 +- Update to 0.1.2 +- Use tar.gz because there are not bz of poppler + +* Wed Mar 2 2005 Marco Pesenti Gritti - 0.1.1-1 +- Initial build