diff --git a/.gitignore b/.gitignore index 0c42acf..eedabbd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -SOURCES/poppler-0.66.0.tar.xz +SOURCES/poppler-20.11.0.tar.xz SOURCES/poppler-test-2009-05-13_0d2bfd4af4c76a3bac27ccaff793d9129df7b57a.tar.xz diff --git a/.poppler.metadata b/.poppler.metadata index d64dede..596bfa9 100644 --- a/.poppler.metadata +++ b/.poppler.metadata @@ -1,2 +1,2 @@ -95f58069ddbeb7db9bee68873266a5dc8aaaef96 SOURCES/poppler-0.66.0.tar.xz +0aa751121aed6ee2220ef3ea16b9df8f9b2e81c1 SOURCES/poppler-20.11.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 index 59524c9..98230f9 100644 --- a/SOURCES/poppler-0.30.0-rotated-words-selection.patch +++ b/SOURCES/poppler-0.30.0-rotated-words-selection.patch @@ -17,269 +17,263 @@ index 7c2ca78..e93908c 100644 --- a/poppler/TextOutputDev.cc +++ b/poppler/TextOutputDev.cc @@ -178,6 +178,12 @@ - #define combMaxMidDelta 0.3 - #define combMaxBaseDelta 0.4 + // to read the underlying image. Issue #157 + #define glyphlessSelectionOpacity 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) ++ true : false) + - 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; + namespace { + + inline bool isAscii7(Unicode uchar) @@ -4411,11 +4417,37 @@ void TextSelectionSizer::visitLine (TextLine *line, - PDFRectangle *rect; - double x1, y1, x2, y2, margin; + 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; -+ } +- 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), + rect = new PDFRectangle(floor(x1 * scale), floor(y1 * scale), ceil(x2 * scale), ceil(y2 * scale)); + list->push_back(rect); @@ -4499,19 +4531,56 @@ void TextSelectionPainter::visitLine (TextLine *line, { - double x1, y1, x2, y2, margin; + 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; -+ } +- 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(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); -+ } +- 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); -+ } +- 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) + ictm.transform(x1, y1, &x1, &y1); + ictm.transform(x2, y2, &x2, &y2); +@@ -4589,17 +4658,26 @@ void TextWord::visitSelection(TextSelectionVisitor *visitor, + void TextWord::visitSelection(TextSelectionVisitor *visitor, const PDFRectangle *selection, SelectionStyle style) { - int i, begin, end; -- double mid; -+ double mid, s1, s2; + 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; -+ } ++ 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; + 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; ++ 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; + /* Skip empty selection. */ +@@ -4615,26 +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; ++ s1 = selection->x1; ++ s2 = selection->x2; + } else { -+ p_min = p->yMin; -+ p_max = p->yMax; ++ 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 (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->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 (((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,41 @@ 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; -+ } ++ 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_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; -+ } - } ++ edge_end = i + 1; ++ } + } - /* Skip empty selection. */ + /* 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 deleted file mode 100644 index 6234822..0000000 --- a/SOURCES/poppler-0.62.0-python3.patch +++ /dev/null @@ -1,8 +0,0 @@ ---- 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 deleted file mode 100644 index ecd52b8..0000000 --- a/SOURCES/poppler-0.66.0-JPXStream-length.patch +++ /dev/null @@ -1,26 +0,0 @@ -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 deleted file mode 100644 index 70f173a..0000000 --- a/SOURCES/poppler-0.66.0-PSOutputDev-rgb.patch +++ /dev/null @@ -1,372 +0,0 @@ -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 deleted file mode 100644 index 73fa712..0000000 --- a/SOURCES/poppler-0.66.0-check-catalog-is-dict.patch +++ /dev/null @@ -1,29 +0,0 @@ ---- 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 deleted file mode 100644 index 74cb731..0000000 --- a/SOURCES/poppler-0.66.0-coverage-values.patch +++ /dev/null @@ -1,35 +0,0 @@ -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; +@@ -3405,6 +3405,7 @@ PopplerFormField *poppler_document_get_f + unsigned fieldNum; + FormPageWidgets *widgets; + FormWidget *field; ++ PopplerFormField *formField; + + FormWidget::decodeID(id, &pageNum, &fieldNum); + +@@ -3417,8 +3418,14 @@ PopplerFormField *poppler_document_get_f + return nullptr; + + field = widgets->getWidget(fieldNum); +- if (field) +- return _poppler_form_field_new(document, field); ++ if (field) { ++ formField = _poppler_form_field_new(document, field); ++ delete widgets; + -+ return formField; -+ } ++ return formField; ++ } + -+ delete widgets; ++ delete widgets; - return nullptr; + 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; +@@ -2921,8 +2921,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/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; +@@ -1619,7 +1619,6 @@ TextBlock::~TextBlock() + + void TextBlock::addWord(TextWord *word) + { +- pool->addWord(word); + if (xMin > xMax) { + xMin = word->xMin; + xMax = word->xMax; +@@ -1639,6 +1638,7 @@ void TextBlock::addWord(TextWord *word) + yMax = word->yMax; + } } - } -+ pool->addWord(word); ++ 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); + void TextBlock::coalesce(const UnicodeMap *uMap, double fixedPitch) +@@ -3064,11 +3064,13 @@ void TextPage::coalesce(bool 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); + fontSize = word0->fontSize; + minBase = maxBase = word0->base; + -+ recList->append (new PDFRectangle(selection_rect->x1, selection_rect->y1, selection_rect->x2, selection_rect->y2)); -+ } ++ blk = new TextBlock(this, rot); ++ blk->addWord(word0); + -+ return recList; -+} -+ - - class TextSelectionPainter : public TextSelectionVisitor { - public: + colSpace1 = minColSpacing1 * fontSize; + colSpace2 = minColSpacing2 * fontSize; + lineSpace = maxLineSpacingDelta * fontSize; +@@ -3095,9 +3097,9 @@ void TextPage::coalesce(bool physLayout, + } + word1 = word1->next; + word2->next = nullptr; ++ newMinBase = word2->base; + blk->addWord(word2); + found = true; +- newMinBase = word2->base; + } else { + word0 = word1; + word1 = word1->next; +@@ -3123,9 +3125,9 @@ void TextPage::coalesce(bool physLayout, + } + word1 = word1->next; + word2->next = nullptr; ++ newMaxBase = word2->base; + blk->addWord(word2); + found = true; +- newMaxBase = word2->base; + } else { + word0 = word1; + word1 = word1->next; +@@ -3198,12 +3200,12 @@ void TextPage::coalesce(bool 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 = true; + break; + } else { +@@ -3246,12 +3248,12 @@ void TextPage::coalesce(bool 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 = true; + break; + } else { --- 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; - } - +@@ -402,6 +402,7 @@ int XRef::reserve(int newSize) + + void *p = greallocn_checkoverflow(entries, realNewSize, sizeof(XRefEntry)); + if (p == nullptr) { ++ entries = nullptr; + return 0; + } + +@@ -835,7 +836,6 @@ bool XRef::constructXRef(bool *wasRecons + int offset = 0; + + resize(0); // free entries properly +- gfree(entries); + capacity = 0; + size = 0; + entries = nullptr; --- poppler/test/pdf-inspector.cc +++ poppler/test/pdf-inspector.cc -@@ -46,6 +46,7 @@ class PdfInspector { +@@ -43,6 +43,7 @@ class PdfInspector + { public: + PdfInspector(); ++ ~PdfInspector(); - 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); + void set_file_name(const char *file_name); + void load(const char *file_name); +@@ -108,6 +109,11 @@ PdfInspector::PdfInspector() + load(nullptr); } -+ + +PdfInspector::~PdfInspector(void) +{ -+ delete output; ++ 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; ++ + void PdfInspector::set_file_name(const char *file_name) + { + GtkWidget *widget; --- 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); +@@ -1337,6 +1337,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; - 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(); - } - } + return; --- 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;
+@@ -329,6 +329,7 @@ int main(int argc, char *argv[])
+             fputs("
\n", f);
+             if (f != stdout) {
+                 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); +@@ -348,8 +349,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->c_str(), physLayout, fixedPitch, rawOrder, htmlMeta, discardDiag); +@@ -390,7 +392,7 @@ int main(int argc, char *argv[]) + 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 deleted file mode 100644 index 698923a..0000000 --- a/SOURCES/poppler-0.66.0-cycles-in-pdf-parsing.patch +++ /dev/null @@ -1,61 +0,0 @@ -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 deleted file mode 100644 index a9f5c58..0000000 --- a/SOURCES/poppler-0.66.0-display-profile.patch +++ /dev/null @@ -1,63 +0,0 @@ -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 deleted file mode 100644 index bc1f5a1..0000000 --- a/SOURCES/poppler-0.66.0-dummy-xref-entry.patch +++ /dev/null @@ -1,63 +0,0 @@ -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 deleted file mode 100644 index a32707f..0000000 --- a/SOURCES/poppler-0.66.0-embedded-file-check.patch +++ /dev/null @@ -1,71 +0,0 @@ -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 deleted file mode 100644 index bfaba8f..0000000 --- a/SOURCES/poppler-0.66.0-filespec.patch +++ /dev/null @@ -1,35 +0,0 @@ -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 deleted file mode 100644 index ce20c07..0000000 --- a/SOURCES/poppler-0.66.0-image-stream-getline.patch +++ /dev/null @@ -1,27 +0,0 @@ -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 deleted file mode 100644 index 2ad86a8..0000000 --- a/SOURCES/poppler-0.66.0-jpeg2000-component-size.patch +++ /dev/null @@ -1,41 +0,0 @@ -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 deleted file mode 100644 index bc2fd6a..0000000 --- a/SOURCES/poppler-0.66.0-negative-object-number.patch +++ /dev/null @@ -1,25 +0,0 @@ -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 deleted file mode 100644 index d0cf40d..0000000 --- a/SOURCES/poppler-0.66.0-negative-xref-indices.patch +++ /dev/null @@ -1,29 +0,0 @@ -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 index 001e528..28db9dc 100644 --- a/SOURCES/poppler-0.66.0-nss.patch +++ b/SOURCES/poppler-0.66.0-nss.patch @@ -28,451 +28,450 @@ index 16476f4f..9f4adda3 100644 +#endif + +#ifdef ENABLE_NSS3 -+static PK11Context *rc4InitContext(const Guchar *key, int keyLen); -+static Guchar rc4DecryptByte(PK11Context *context, Guchar c); ++static PK11Context *rc4InitContext(const unsigned char *key, int keyLen); ++static unsigned char rc4DecryptByte(PK11Context *context, unsigned char c); +#else - static void rc4InitKey(Guchar *key, int keyLen, Guchar *state); - static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c); + static void rc4InitKey(const unsigned char *key, int keyLen, unsigned char *state); + static unsigned char rc4DecryptByte(unsigned char *state, unsigned char *x, unsigned char *y, unsigned char c); +#endif - static GBool aesReadBlock(Stream *str, Guchar *in, GBool addPadding); + static bool aesReadBlock(Stream *str, unsigned char *in, bool addPadding); +#ifdef ENABLE_NSS3 -+static PK11Context *aesInitContext(Guchar *in, Guchar *objKey, int objKeyLength, GBool decrypt); ++static PK11Context *aesInitContext(unsigned char *in, unsigned char *objKey, int objKeyLength, bool decrypt); +#else - static void aesKeyExpansion(DecryptAESState *s, Guchar *objKey, int objKeyLen, GBool decrypt); + static void aesKeyExpansion(DecryptAESState *s, const unsigned char *objKey, int objKeyLen, bool decrypt); +#endif - static void aesEncryptBlock(DecryptAESState *s, Guchar *in); - static void aesDecryptBlock(DecryptAESState *s, Guchar *in, GBool last); + static void aesEncryptBlock(DecryptAESState *s, const unsigned char *in); + static void aesDecryptBlock(DecryptAESState *s, const unsigned char *in, bool last); +#ifndef ENABLE_NSS3 - static void aes256KeyExpansion(DecryptAES256State *s, Guchar *objKey, int objKeyLen, GBool decrypt); + static void aes256KeyExpansion(DecryptAES256State *s, const unsigned char *objKey, int objKeyLen, bool decrypt); +#endif - static void aes256EncryptBlock(DecryptAES256State *s, Guchar *in); - static void aes256DecryptBlock(DecryptAES256State *s, Guchar *in, GBool last); + static void aes256EncryptBlock(DecryptAES256State *s, const unsigned char *in); + static void aes256DecryptBlock(DecryptAES256State *s, const unsigned char *in, bool last); -@@ -70,6 +86,31 @@ static const Guchar passwordPad[32] = { +@@ -70,6 +86,31 @@ static const unsigned char 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)); -+ } ++ 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; ++static bool initNSS() { ++ if (NSS_IsInitialized()) { ++ return true; + } else { -+ atexit(shutdownNSS); -+ return gTrue; ++ if (NSS_NoDB_Init(".") != SECSuccess) { ++ error(errInternal, -1, "NSS initialization failed: {0:s}", ++ PR_ErrorToString(PR_GetError(), PR_LANGUAGE_I_DEFAULT)); ++ return false; ++ } else { ++ atexit(shutdownNSS); ++ return true; ++ } + } -+ } +} +#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; + bool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, const GooString *ownerKey, const GooString *userKey, const GooString *ownerEnc, const GooString *userEnc, int permissions, const GooString *fileID, + const GooString *ownerPassword, const GooString *userPassword, unsigned char *fileKey, bool encryptMetadata, bool *ownerPasswordOk) + { +@@ -80,13 +121,21 @@ bool Decrypt::makeFileKey(int encVersio + DecryptAES256State state; + unsigned char test[127 + 56], test2[32]; + GooString *userPassword2; +- unsigned char fState[256]; + unsigned char tmpKey[16]; +- unsigned char fx, fy; + int len, i, j; +#ifdef ENABLE_NSS3 -+ PK11Context *rc4Context; ++ PK11Context *rc4Context; +#else -+ Guchar fState[256]; -+ Guchar fx, fy; ++ unsigned char fState[256]; ++ unsigned char fx, fy; +#endif - *ownerPasswordOk = gFalse; + *ownerPasswordOk = false; +#ifdef ENABLE_NSS3 -+ initNSS(); ++ initNSS(); +#endif + - if (encRevision == 5 || encRevision == 6) { + 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()); - } + // check the owner password +@@ -115,14 +164,26 @@ bool Decrypt::makeFileKey(int encVersio + // test contains the initial SHA-256 hash input K. + revision6Hash(ownerPassword, test, userKey->c_str()); + } +#ifndef ENABLE_NSS3 - aes256KeyExpansion(&state, test, 32, gTrue); + aes256KeyExpansion(&state, test, 32, true); +#endif - for (i = 0; i < 16; ++i) { - state.cbc[i] = 0; - } + for (i = 0; i < 16; ++i) { + state.cbc[i] = 0; + } +#ifdef ENABLE_NSS3 -+ state.context = aesInitContext(state.cbc, test, 32, gTrue); -+ if (state.context) { ++ state.context = aesInitContext(state.cbc, test, 32, true); ++ 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); + aes256DecryptBlock(&state, (unsigned char *)ownerEnc->c_str(), false); + memcpy(fileKey, state.buf, 16); + aes256DecryptBlock(&state, (unsigned char *)ownerEnc->c_str() + 16, false); + memcpy(fileKey + 16, state.buf, 16); +#ifdef ENABLE_NSS3 -+ PK11_DestroyContext(state.context, PR_TRUE); -+ } else { -+ return gFalse; -+ } ++ PK11_DestroyContext(state.context, PR_TRUE); ++ } else { ++ return false; ++ } +#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); - } + *ownerPasswordOk = true; + return true; +@@ -156,14 +217,26 @@ bool 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); + aes256KeyExpansion(&state, test, 32, true); +#endif - for (i = 0; i < 16; ++i) { - state.cbc[i] = 0; - } + for (i = 0; i < 16; ++i) { + state.cbc[i] = 0; + } +#ifdef ENABLE_NSS3 -+ state.context = aesInitContext(state.cbc, test, 32, gTrue); -+ if (state.context) { ++ state.context = aesInitContext(state.cbc, test, 32, true); ++ 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); + aes256DecryptBlock(&state, (unsigned char *)userEnc->c_str(), false); + memcpy(fileKey, state.buf, 16); + aes256DecryptBlock(&state, (unsigned char *)userEnc->c_str() + 16, false); + memcpy(fileKey + 16, state.buf, 16); +#ifdef ENABLE_NSS3 -+ PK11_DestroyContext(state.context, PR_TRUE); -+ } else { -+ return gFalse; -+ } ++ PK11_DestroyContext(state.context, PR_TRUE); ++ } else { ++ return false; ++ } +#endif - return gTrue; - } -@@ -189,22 +262,41 @@ GBool Decrypt::makeFileKey(int encVersio - } - } - if (encRevision == 2) { + return true; + } +@@ -189,22 +262,41 @@ bool 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); -+ } ++ 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)); - } + 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; - } + } else { + memcpy(test2, ownerKey->c_str(), 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); -+ } ++ 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]); - } + 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; + } + } + userPassword2 = new GooString((char *)test2, 32); +@@ -232,11 +324,15 @@ bool Decrypt::makeFileKey2(int encVersi + { + unsigned char *buf; + unsigned char test[32]; +- unsigned char fState[256]; + unsigned char tmpKey[16]; +- unsigned char fx, fy; + int len, i, j; +- bool ok; ++ bool ok = true; +#ifdef ENABLE_NSS3 -+ PK11Context *rc4Context; ++ PK11Context *rc4Context; +#else -+ Guchar fState[256]; -+ Guchar fx, fy; ++ unsigned char fState[256]; ++ unsigned char fx, fy; +#endif - // generate file key - buf = (Guchar *)gmalloc(72 + fileID->getLength()); -@@ -273,28 +369,52 @@ GBool Decrypt::makeFileKey2(int encVersi + // generate file key + buf = (unsigned char *)gmalloc(72 + fileID->getLength()); +@@ -273,28 +369,52 @@ bool Decrypt::makeFileKey2(int encVersi - // test user password - if (encRevision == 2) { + // 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; -+ } ++ 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 = false; ++ } +#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; + 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; - } ++ if (ok) ++ ok = memcmp(test, passwordPad, 32) == 0; + } else if (encRevision == 3) { + memcpy(test, userKey->c_str(), 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; -+ } ++ 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 = false; ++ } +#else - rc4InitKey(tmpKey, keyLength, fState); - fx = fy = 0; - for (j = 0; j < 32; ++j) { - test[j] = rc4DecryptByte(fState, &fx, &fy, test[j]); - } + 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->c_str(), fileID->getLength()); + md5(buf, 32 + fileID->getLength(), buf); +- ok = memcmp(test, buf, 16) == 0; ++ if (ok) ++ ok = memcmp(test, buf, 16) == 0; + } else { + ok = false; } - 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; - } + if ((objKeyLength = keyLength + 5) > 16) { + objKeyLength = 16; + } +#ifdef ENABLE_NSS3 -+ state.rc4.context = nullptr; ++ state.rc4.context = nullptr; +#endif - break; - case cryptAES: - objKey[keyLength] = objNum & 0xff; + break; + case cryptAES: + objKey[keyLength] = refA.num & 0xff; @@ -349,9 +472,15 @@ BaseCryptStream::BaseCryptStream(Stream - if ((objKeyLength = keyLength + 5) > 16) { - objKeyLength = 16; - } + if ((objKeyLength = keyLength + 5) > 16) { + objKeyLength = 16; + } +#ifdef ENABLE_NSS3 -+ state.aes.context = nullptr; ++ state.aes.context = nullptr; +#endif - break; - case cryptAES256: - objKeyLength = keyLength; + break; + case cryptAES256: + objKeyLength = keyLength; +#ifdef ENABLE_NSS3 -+ state.aes256.context = nullptr; ++ state.aes256.context = nullptr; +#endif - break; - case cryptNone: - break; -@@ -359,9 +488,32 @@ BaseCryptStream::BaseCryptStream(Stream - - charactersRead = 0; - autoDelete = gTrue; + break; + case cryptNone: + break; +@@ -359,10 +488,33 @@ BaseCryptStream::BaseCryptStream(Stream + charactersRead = 0; + nextCharBuff = EOF; + autoDelete = true; + +#ifdef ENABLE_NSS3 -+ initNSS(); ++ initNSS(); +#endif } - BaseCryptStream::~BaseCryptStream() { + 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; -+ } ++ 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; - } + if (autoDelete) { + delete str; + } @@ -424,18 +576,40 @@ void EncryptStream::reset() { - switch (algo) { - case cryptRC4: + switch (algo) { + case cryptRC4: +#ifdef ENABLE_NSS3 -+ if (state.rc4.context) -+ PK11_DestroyContext(state.rc4.context, PR_TRUE); -+ state.rc4.context = rc4InitContext(objKey, objKeyLength); ++ 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); + state.rc4.x = state.rc4.y = 0; + rc4InitKey(objKey, objKeyLength, state.rc4.state); +#endif - break; - case cryptAES: + 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); ++ 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, ++ false); +#else - aesKeyExpansion(&state.aes, objKey, objKeyLength, gFalse); - memcpy(state.aes.buf, state.aes.cbc, 16); // Copy CBC IV to buf + aesKeyExpansion(&state.aes, objKey, objKeyLength, false); + 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: + state.aes.bufIdx = 0; + state.aes.paddingReached = false; + 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); ++ 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, ++ false); +#else - aes256KeyExpansion(&state.aes256, objKey, objKeyLength, gFalse); - memcpy(state.aes256.buf, state.aes256.cbc, 16); // Copy CBC IV to buf + aes256KeyExpansion(&state.aes256, objKey, objKeyLength, false); + memcpy(state.aes256.buf, state.aes256.cbc, 16); // Copy CBC IV to buf +#endif - state.aes256.bufIdx = 0; - state.aes256.paddingReached = gFalse; - break; + state.aes256.bufIdx = 0; + state.aes256.paddingReached = false; + 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 + 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); ++ c = rc4DecryptByte(state.rc4.context, (unsigned char)c); +#else - c = rc4DecryptByte(state.rc4.state, &state.rc4.x, &state.rc4.y, (Guchar)c); + c = rc4DecryptByte(state.rc4.state, &state.rc4.x, &state.rc4.y, (unsigned char)c); +#endif - } - break; - case cryptAES: + } + break; + case cryptAES: @@ -506,21 +684,47 @@ void DecryptStream::reset() { - switch (algo) { - case cryptRC4: + switch (algo) { + case cryptRC4: +#ifdef ENABLE_NSS3 -+ if (state.rc4.context) -+ PK11_DestroyContext(state.rc4.context, PR_TRUE); -+ state.rc4.context = rc4InitContext(objKey, objKeyLength); ++ 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); + state.rc4.x = state.rc4.y = 0; + rc4InitKey(objKey, objKeyLength, state.rc4.state); +#endif - break; - case cryptAES: + 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); ++ 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, ++ true); +#else - aesKeyExpansion(&state.aes, objKey, objKeyLength, gTrue); - for (i = 0; i < 16; ++i) { - state.aes.cbc[i] = str->getChar(); - } + aesKeyExpansion(&state.aes, objKey, objKeyLength, true); + for (i = 0; i < 16; ++i) { + state.aes.cbc[i] = str->getChar(); + } +#endif - state.aes.bufIdx = 16; - break; - case cryptAES256: + 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); ++ 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, ++ true); +#else - aes256KeyExpansion(&state.aes256, objKey, objKeyLength, gTrue); - for (i = 0; i < 16; ++i) { - state.aes256.cbc[i] = str->getChar(); - } + aes256KeyExpansion(&state.aes256, objKey, objKeyLength, true); + for (i = 0; i < 16; ++i) { + state.aes256.cbc[i] = str->getChar(); + } +#endif - state.aes256.bufIdx = 16; - break; - case cryptNone: + state.aes256.bufIdx = 16; + break; + case cryptNone: @@ -539,10 +743,21 @@ int DecryptStream::lookChar() { - switch (algo) { - case cryptRC4: - if ((c = str->getChar()) != EOF) { + 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); ++ if (unlikely(state.rc4.context == nullptr)) ++ c = EOF; ++ else ++ c = rc4DecryptByte(state.rc4.context, (unsigned char)c); +#else - c = rc4DecryptByte(state.rc4.state, &state.rc4.x, &state.rc4.y, (Guchar)c); + c = rc4DecryptByte(state.rc4.state, &state.rc4.x, &state.rc4.y, (unsigned char)c); +#endif - } - break; - case cryptAES: + } + break; + case cryptAES: +#ifdef ENABLE_NSS3 -+ if (unlikely(state.aes.context == nullptr)) -+ break; ++ 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); + if (state.aes.bufIdx == 16) { + if (aesReadBlock(str, in, false)) { + aesDecryptBlock(&state.aes, in, str->lookChar() == EOF); @@ -555,6 +770,10 @@ int DecryptStream::lookChar() { - } - break; - case cryptAES256: + } + break; + case cryptAES256: +#ifdef ENABLE_NSS3 -+ if (unlikely(state.aes256.context == nullptr)) -+ break; ++ 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() { + if (state.aes256.bufIdx == 16) { + if (aesReadBlock(str, in, false)) { + aes256DecryptBlock(&state.aes256, in, str->lookChar() == EOF); +@@ -576,7 +795,176 @@ int DecryptStream::lookChar() { // RC4-compatible decryption //------------------------------------------------------------------------ @@ -481,175 +480,176 @@ index 16476f4f..9f4adda3 100644 + * 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, ++static PK11SymKey *tokenizeKey(const unsigned char *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()); -+ } ++ 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; ++ unsigned char output[48]; // Buffer to hold 256 bit key + padding ++ unsigned char iv[16]; // Initialization vector for AES ++ unsigned int 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; ++ } + -+err: -+ if (secParam != nullptr) -+ SECITEM_FreeItem(secParam, PR_TRUE); ++ // 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; ++ } + -+ if (wrappingKey != nullptr) -+ PK11_FreeSymKey(wrappingKey); ++ for (i = 0; i < 16; i++) ++ iv[i] = i; + -+ if (symKey != nullptr) -+ PK11_FreeSymKey(symKey); ++ ivItem.type = siBuffer; ++ ivItem.data = iv; ++ ivItem.len = 16; + -+ if (slot != nullptr) -+ PK11_FreeSlot(slot); ++ secParam = PK11_ParamFromIV(cipherMech, &ivItem); ++ if (secParam == nullptr) { ++ error(errInternal, -1, "Failed to set up PKCS11 param (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } + -+ return token; -+} ++ // 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()); ++ } + -+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()); -+ } ++ 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 (secParam != nullptr) ++ SECITEM_FreeItem(secParam, PR_TRUE); + -+ if (symKey != nullptr) -+ PK11_FreeSymKey(symKey); ++ if (wrappingKey != nullptr) ++ PK11_FreeSymKey(wrappingKey); + -+ if (slot != nullptr) -+ PK11_FreeSlot(slot); ++ if (symKey != nullptr) ++ PK11_FreeSymKey(symKey); + -+ return context; ++ if (slot != nullptr) ++ PK11_FreeSlot(slot); ++ ++ return token; +} + -+static Guchar rc4DecryptByte(PK11Context *context, Guchar c) { -+ Guchar outputChar = 0; -+ SECStatus retval; -+ int outputLength; ++static PK11Context *rc4InitContext(const unsigned char *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; ++ } + -+ retval = PK11_CipherOp(context, -+ &outputChar, -+ &outputLength, -+ 1, -+ &c, -+ 1); ++ 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 (retval != SECSuccess) { -+ error(errInternal, -1, "Failed to decrypt byte (err {0:d})", -+ PR_GetError()); -+ } ++ if (symKey != nullptr) ++ PK11_FreeSymKey(symKey); + -+ return outputChar; ++ if (slot != nullptr) ++ PK11_FreeSlot(slot); ++ ++ return context; ++} ++ ++static unsigned char rc4DecryptByte(PK11Context *context, unsigned char c) { ++ unsigned char 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]; + static void rc4InitKey(const unsigned char *key, int keyLen, unsigned char *state) + { + unsigned char index1, index2; + unsigned char t; +@@ -609,6 +997,8 @@ static unsigned char rc4DecryptByte(unsigned char *sta + return c ^ state[(tx + ty) % 256]; } +#endif @@ -657,187 +657,187 @@ index 16476f4f..9f4adda3 100644 //------------------------------------------------------------------------ // AES decryption //------------------------------------------------------------------------ -@@ -639,6 +1029,178 @@ static GBool aesReadBlock(Stream *str, G - } +@@ -639,6 +1029,178 @@ static bool 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); ++static PK11Context *aesInitContext(unsigned char *in, unsigned char *objKey, ++ int objKeyLength, bool 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; ++ } + -+err: -+ if (secParam != nullptr) -+ SECITEM_FreeItem(secParam, PR_TRUE); ++ symKey = tokenizeKey(objKey, objKeyLength, cipherMech); ++ if (symKey == nullptr) { ++ error(errInternal, -1, "Failed to create token from key (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } + -+ if (symKey != nullptr) -+ PK11_FreeSymKey(symKey); ++ ivItem.type = siBuffer; ++ ivItem.data = in; ++ ivItem.len = 16; + -+ if (slot != nullptr) -+ PK11_FreeSlot(slot); ++ secParam = PK11_ParamFromIV(cipherMech, &ivItem); ++ if (secParam == nullptr) { ++ error(errInternal, -1, "Failed to set up PKCS11 param (err {0:d})", ++ PR_GetError()); ++ goto err; ++ } + -+ return context; -+} ++ context = PK11_CreateContextBySymKey(cipherMech, ++ operationType, ++ symKey, ++ secParam); ++ ++err: ++ if (secParam != nullptr) ++ SECITEM_FreeItem(secParam, PR_TRUE); + -+static void aesEncryptBlock(DecryptAESState *s, Guchar *in) { -+ SECStatus rv; -+ int outputLength; ++ if (symKey != nullptr) ++ PK11_FreeSymKey(symKey); + -+ rv = PK11_CipherOp(s->context, -+ s->buf, -+ &outputLength, -+ 16, -+ in, -+ 16); ++ if (slot != nullptr) ++ PK11_FreeSlot(slot); + -+ if (rv != SECSuccess) { -+ error(errInternal, -1, "Failed to encrypt input block (err {0:d})", -+ PR_GetError()); -+ goto err; -+ } ++ return context; ++} ++ ++static void aesEncryptBlock(DecryptAESState *s, const unsigned char *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; ++ s->bufIdx = 0; + +err: -+ return; ++ 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; ++static void aesDecryptBlock(DecryptAESState *s, const unsigned char *in, bool 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; + } -+ for (i = 15; i >= n; --i) { -+ s->buf[i] = s->buf[i-n]; ++ ++ 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; + } -+ s->bufIdx = n; -+ } + +err: -+ return; ++ 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; -+ } ++static void aes256EncryptBlock(DecryptAES256State *s, const unsigned char *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; ++ s->bufIdx = 0; + +err: -+ return; ++ 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; ++static void aes256DecryptBlock(DecryptAES256State *s, const unsigned char *in, ++ bool 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; + } -+ for (i = 15; i >= n; --i) { -+ s->buf[i] = s->buf[i-n]; ++ ++ 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; + } -+ s->bufIdx = n; -+ } + +err: -+ return; ++ 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, + static const unsigned char 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, + 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, + 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, @@ -1121,10 +1683,33 @@ static void aes256DecryptBlock(DecryptAE - } + } } +#endif @@ -847,46 +847,47 @@ index 16476f4f..9f4adda3 100644 //------------------------------------------------------------------------ +#ifdef ENABLE_NSS3 -+static void hashFunc(const Guchar *msg, int msgLen, Guchar *hash, ++static void hashFunc(const unsigned char *msg, int msgLen, unsigned char *hash, + HASH_HashType type) { -+ HASHContext *context; -+ Guint hashLen = 0; ++ HASHContext *context; ++ unsigned int hashLen = 0; + -+ if (!initNSS()) -+ return; ++ if (!initNSS()) ++ return; + -+ context = HASH_Create(type); -+ if (context == nullptr) -+ 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); ++ 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); + static inline unsigned long rotateLeft(unsigned long x, int r) + { +@@ -1151,8 +1736,13 @@ static inline unsigned long md5Round4(unsigned long a, + state->digest[15] = (unsigned char)(state->d >> 24); } +#endif + - void md5(Guchar *msg, int msgLen, Guchar *digest) { + void md5(const unsigned char *msg, int msgLen, unsigned char *digest) + { +#ifdef ENABLE_NSS3 -+ hashFunc(msg, msgLen, digest, HASH_AlgMD5); ++ 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); + if (msgLen < 0) { + return; + } +@@ -1296,12 +1886,14 @@ void md5(unsigned char *msg, int msgLen, unsigned char + for (int i = 0; i < 16; ++i) { + digest[i] = state.digest[i]; + } +#endif } @@ -895,26 +896,27 @@ index 16476f4f..9f4adda3 100644 //------------------------------------------------------------------------ +#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; + static const unsigned int sha256K[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, +@@ -1400,9 +1992,13 @@ static void sha256HashBlock(unsigned char *blk, + H[6] += g; + H[7] += h; } +#endif - static void sha256(Guchar *msg, int msgLen, Guchar *hash) { + static void sha256(unsigned char *msg, int msgLen, unsigned char *hash) + { +#ifdef ENABLE_NSS3 -+ hashFunc(msg, msgLen, hash, HASH_AlgSHA256); ++ 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]; - } + unsigned char blk[64]; + unsigned int H[8]; + int blkLen, i; +@@ -1453,7 +2049,10 @@ static void sha256(unsigned char *msg, int msgL + hash[i * 4 + 2] = (unsigned char)(H[i] >> 8); + hash[i * 4 + 3] = (unsigned char)H[i]; + } +#endif } + @@ -922,76 +924,67 @@ index 16476f4f..9f4adda3 100644 //------------------------------------------------------------------------ // SHA-512 hash (see FIPS 180-4) //------------------------------------------------------------------------ -@@ -1557,8 +2156,12 @@ static void sha512HashBlock(Guchar *blk, - H[6] += g; - H[7] += h; +@@ -1557,9 +2156,13 @@ static void sha512HashBlock(unsigned char *blk, + H[6] += g; + H[7] += h; } +#endif - static void sha512(Guchar *msg, int msgLen, Guchar *hash) { + static void sha512(unsigned char *msg, int msgLen, unsigned char *hash) + { +#ifdef ENABLE_NSS3 -+ hashFunc(msg, msgLen, hash, HASH_AlgSHA512); ++ 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]; - } + unsigned char blk[128]; + uint64_t H[8]; + int blkLen = 0, i; +@@ -1622,6 +2225,7 @@ static void sha512(unsigned char *msg, int msgL + hash[i * 8 + 6] = (unsigned char)(H[i] >> 8); + hash[i * 8 + 7] = (unsigned char)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) { +@@ -1631,6 +2235,9 @@ static void sha512(unsigned char *msg, int msgL + // 2.A 384 bit message digest is obtained by truncating the final hash value. + static void sha384(unsigned char *msg, int msgLen, unsigned char *hash) + { +#ifdef ENABLE_NSS3 -+ hashFunc(msg, msgLen, hash, HASH_AlgSHA384); ++ 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]; - } + unsigned char blk[128]; + uint64_t H[8]; + int blkLen, i; +@@ -1696,6 +2303,7 @@ static void sha384(unsigned char *msg, int msgL + hash[i * 8 + 6] = (unsigned char)(H[i] >> 8); + hash[i * 8 + 7] = (unsigned char)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; + memcpy(state.buf, state.cbc, 16); // Copy CBC IV to buf + state.bufIdx = 0; + state.paddingReached = false; +#ifdef ENABLE_NSS3 -+ state.context = aesInitContext(state.cbc, aesKey, 16, gFalse); ++ state.context = aesInitContext(state.cbc, aesKey, 16, false); +#else - aesKeyExpansion(&state,aesKey,16,gFalse); + aesKeyExpansion(&state, aesKey, 16, false); +#endif - for(int i = 0; i < (4 * sequenceLength); i++) { - aesEncryptBlock(&state,K1 + (16 * i)); + 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++; + sha512(E, totalLength, K); + } + rounds++; +#ifdef ENABLE_NSS3 -+ PK11_DestroyContext(state.context, PR_TRUE); ++ PK11_DestroyContext(state.context, PR_TRUE); +#endif - } - // the first 32 bytes of the final K are the output of the function. + } + // 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 @@ -1007,47 +1000,48 @@ index d4667c8c..16fa9830 100644 //------------------------------------------------------------------------ // Decrypt -@@ -73,13 +77,21 @@ private: - * previous output is kept in buf. The paddingReached field is only used in +@@ -73,14 +77,22 @@ private: * case of encryption. */ - struct DecryptRC4State { + struct DecryptRC4State + { +#ifdef ENABLE_NSS3 -+ PK11Context *context; ++ PK11Context *context; +#else - Guchar state[256]; - Guchar x, y; + unsigned char state[256]; + unsigned char x, y; +#endif }; - struct DecryptAESState { + struct DecryptAESState + { +#ifdef ENABLE_NSS3 -+ PK11Context *context; ++ PK11Context *context; +#else - Guint w[44]; - Guchar state[16]; + unsigned int w[44]; + unsigned char state[16]; +#endif - Guchar cbc[16]; - Guchar buf[16]; - GBool paddingReached; // encryption only + unsigned char cbc[16]; + unsigned char buf[16]; + bool paddingReached; // encryption only @@ -87,8 +99,12 @@ struct DecryptAESState { - }; - struct DecryptAES256State { + struct DecryptAES256State + { +#ifdef ENABLE_NSS3 -+ PK11Context *context; ++ PK11Context *context; +#else - Guint w[60]; - Guchar state[16]; + unsigned int w[60]; + unsigned char state[16]; +#endif - Guchar cbc[16]; - Guchar buf[16]; - GBool paddingReached; // encryption only + unsigned char cbc[16]; + unsigned char buf[16]; + bool 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 + #cmakedefine USE_BOOST_HEADERS 1 #endif +/* Build against libnss3 for digital signature validation and @@ -1056,17 +1050,6 @@ index f0a5a1a0..dcaade6f 100644 +#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}") + //------------------------------------------------------------------------ + // version + //------------------------------------------------------------------------ diff --git a/SOURCES/poppler-0.66.0-rescale-filter.patch b/SOURCES/poppler-0.66.0-rescale-filter.patch deleted file mode 100644 index 3dbad5c..0000000 --- a/SOURCES/poppler-0.66.0-rescale-filter.patch +++ /dev/null @@ -1,100 +0,0 @@ -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 deleted file mode 100644 index 3730e3e..0000000 --- a/SOURCES/poppler-0.66.0-rich-media-annotation.patch +++ /dev/null @@ -1,51 +0,0 @@ -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 deleted file mode 100644 index 1f6d53f..0000000 --- a/SOURCES/poppler-0.66.0-stack-overflow.patch +++ /dev/null @@ -1,20 +0,0 @@ -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 deleted file mode 100644 index 3a4ba07..0000000 --- a/SOURCES/poppler-0.66.0-stream-check.patch +++ /dev/null @@ -1,28 +0,0 @@ -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 deleted file mode 100644 index ea17a49..0000000 --- a/SOURCES/poppler-0.66.0-tiling-patterns.patch +++ /dev/null @@ -1,47 +0,0 @@ -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 deleted file mode 100644 index b85bcfe..0000000 --- a/SOURCES/poppler-0.66.0-tilingpatternfill-crash.patch +++ /dev/null @@ -1,28 +0,0 @@ -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 deleted file mode 100644 index 6f0a841..0000000 --- a/SOURCES/poppler-0.66.0-valid-embedded-file-name.patch +++ /dev/null @@ -1,81 +0,0 @@ -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 deleted file mode 100644 index 1880a0d..0000000 --- a/SOURCES/poppler-0.66.0-valid-embedded-file.patch +++ /dev/null @@ -1,46 +0,0 @@ -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 index 8f76ef9..e1accfd 100644 --- a/SPECS/poppler.spec +++ b/SPECS/poppler.spec @@ -3,8 +3,8 @@ Summary: PDF rendering library Name: poppler -Version: 0.66.0 -Release: 27%{?dist} +Version: 20.11.0 +Release: 1%{?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 @@ -14,77 +14,13 @@ 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) @@ -190,6 +126,7 @@ other formats. %prep %autosetup -p1 -b 1 +chmod -x poppler/CairoFontEngine.cc %build mkdir build @@ -200,9 +137,10 @@ export CC="gcc -fPIC" # hack to make the cmake call pass -DENABLE_DCTDECODER=libjpeg \ -DENABLE_GTK_DOC=ON \ -DENABLE_LIBOPENJPEG=openjpeg2 \ - -DENABLE_XPDF_HEADERS=ON \ -DENABLE_ZLIB=OFF \ -DENABLE_NSS=ON \ + -DENABLE_UNSTABLE_API_ABI_HEADERS=ON \ + -DENABLE_QT6=OFF \ .. unset CC make %{?_smp_mflags} @@ -236,9 +174,9 @@ test "$(pkg-config --modversion poppler-splash)" = "%{version}" %postun cpp -p /sbin/ldconfig %files -%doc README +%doc README.md %license COPYING -%{_libdir}/libpoppler.so.78* +%{_libdir}/libpoppler.so.104* %files devel %{_libdir}/pkgconfig/poppler.pc @@ -287,6 +225,11 @@ test "$(pkg-config --modversion poppler-splash)" = "%{version}" %{_mandir}/man1/* %changelog +* Fri Nov 6 2020 Marek Kasik - 20.11.0-1 +- Rebase poppler to 20.11.0 +- Modify/remove patches as needed +- Resolves: #1644423 + * Thu Apr 16 2020 Marek Kasik - 0.66.0-27 - Fix crash on broken file in tilingPatternFill() - Resolves: #1801341