From 64828896a3bff4adafd2f3cac766165bb09a32a1 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Sun, 2 Jun 2024 21:05:18 +0200 Subject: [PATCH 01/27] poppler 24.06.0 --- CMakeLists.txt | 2 +- NEWS | 15 +++++++++++++++ cpp/Doxyfile | 2 +- qt5/src/Doxyfile | 2 +- qt6/src/Doxyfile | 2 +- 5 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 35df6d292..66c526d9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,7 @@ if (ECM_FOUND) endif() set(POPPLER_MAJOR_VERSION "24") -set(POPPLER_MINOR_VERSION_STRING "05") +set(POPPLER_MINOR_VERSION_STRING "06") # We want the string version to have 08 but the integer version can't have a leading 0 since otherwise it's considered octal # So strip a leading 0 if found in POPPLER_MINOR_VERSION_STRING and store the result in POPPLER_MINOR_VERSION string(REGEX REPLACE "^0?(.+)$" "\\1" POPPLER_MINOR_VERSION "${POPPLER_MINOR_VERSION_STRING}") diff --git a/NEWS b/NEWS index 1e07d927d..a0f4b5291 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,18 @@ +Release 24.06.0: + core: + * Performance improvements in some files + * Fix some issues with files bigger than 2^31 bytes + * Remove all cairo include guards for cairo < 1.16 + * Fix MSVC build + * Internal code improvements + + qt6: + * Update Qt6 doc example + * Use the non deprecated version of QString::fromUcs4 + + glib: + * properly document return value from poppler_font_info_scan + Release 24.05.0: core: * Fix signing not being totally correct in some kind of PDF files diff --git a/cpp/Doxyfile b/cpp/Doxyfile index deee0ab16..ddc785cbe 100644 --- a/cpp/Doxyfile +++ b/cpp/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = "Poppler CPP" # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 24.05.0 +PROJECT_NUMBER = 24.06.0 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. diff --git a/qt5/src/Doxyfile b/qt5/src/Doxyfile index b196bfd6a..32c64bb41 100644 --- a/qt5/src/Doxyfile +++ b/qt5/src/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = "Poppler Qt5" # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 24.05.0 +PROJECT_NUMBER = 24.06.0 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. diff --git a/qt6/src/Doxyfile b/qt6/src/Doxyfile index d3911df8a..66f8fc6c0 100644 --- a/qt6/src/Doxyfile +++ b/qt6/src/Doxyfile @@ -31,7 +31,7 @@ PROJECT_NAME = "Poppler Qt6" # This could be handy for archiving the generated documentation or # if some version control system is used. -PROJECT_NUMBER = 24.05.0 +PROJECT_NUMBER = 24.06.0 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. From 938af005733a77b13cee2086469ad9eed8e1997c Mon Sep 17 00:00:00 2001 From: Sune Vuorela Date: Thu, 6 Jun 2024 20:54:19 +0000 Subject: [PATCH 02/27] GfxFonts: Switch font widths from pointer, length to std::vector --- poppler/GfxFont.cc | 65 ++++++++++------------------------------------ poppler/GfxFont.h | 7 ++--- 2 files changed, 16 insertions(+), 56 deletions(-) diff --git a/poppler/GfxFont.cc b/poppler/GfxFont.cc index 9d17f12eb..91b798d9a 100644 --- a/poppler/GfxFont.cc +++ b/poppler/GfxFont.cc @@ -1733,7 +1733,6 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, std::optionallookup("W"); if (obj1.isArray()) { - excepsSize = 0; int i = 0; while (i + 1 < obj1.arrayGetLength()) { obj2 = obj1.arrayGet(i); @@ -1871,33 +1865,21 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, std::optional(obj2.getInt()), static_cast(obj3.getInt()), obj4.getNum() * 0.001 }; + widths.exceps.push_back(excep); } else { error(errSyntaxError, -1, "Bad widths array in Type 0 font"); } i += 3; } else if (obj2.isInt() && obj3.isArray()) { - if (widths.nExceps + obj3.arrayGetLength() > excepsSize) { - excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15; - widths.exceps = (GfxFontCIDWidthExcep *)greallocn(widths.exceps, excepsSize, sizeof(GfxFontCIDWidthExcep)); - } int j = obj2.getInt(); if (likely(j < INT_MAX - obj3.arrayGetLength())) { for (int k = 0; k < obj3.arrayGetLength(); ++k) { obj4 = obj3.arrayGet(k); if (obj4.isNum()) { - widths.exceps[widths.nExceps].first = j; - widths.exceps[widths.nExceps].last = j; - widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001; + GfxFontCIDWidthExcep excep { static_cast(j), static_cast(j), obj4.getNum() * 0.001 }; + widths.exceps.push_back(excep); ++j; - ++widths.nExceps; } else { error(errSyntaxError, -1, "Bad widths array in Type 0 font"); } @@ -1909,7 +1891,7 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, std::optionallookup("W2"); if (obj1.isArray()) { - excepsSize = 0; int i = 0; while (i + 1 < obj1.arrayGetLength()) { obj2 = obj1.arrayGet(i); obj3 = obj1.arrayGet(i + 1); if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) { if ((obj4 = obj1.arrayGet(i + 2), obj4.isNum()) && (obj5 = obj1.arrayGet(i + 3), obj5.isNum()) && (obj6 = obj1.arrayGet(i + 4), obj6.isNum())) { - if (widths.nExcepsV == excepsSize) { - excepsSize += 16; - widths.excepsV = (GfxFontCIDWidthExcepV *)greallocn(widths.excepsV, excepsSize, sizeof(GfxFontCIDWidthExcepV)); - } - widths.excepsV[widths.nExcepsV].first = obj2.getInt(); - widths.excepsV[widths.nExcepsV].last = obj3.getInt(); - widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001; - widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001; - widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001; - ++widths.nExcepsV; + GfxFontCIDWidthExcepV excepV { static_cast(obj2.getInt()), static_cast(obj3.getInt()), obj4.getNum() * 0.001, obj5.getNum() * 0.001, obj6.getNum() * 0.001 }; + widths.excepsV.push_back(excepV); } else { error(errSyntaxError, -1, "Bad widths (W2) array in Type 0 font"); } i += 5; } else if (obj2.isInt() && obj3.isArray()) { - if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) { - excepsSize = (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15; - widths.excepsV = (GfxFontCIDWidthExcepV *)greallocn(widths.excepsV, excepsSize, sizeof(GfxFontCIDWidthExcepV)); - } int j = obj2.getInt(); for (int k = 0; k < obj3.arrayGetLength(); k += 3) { if ((obj4 = obj3.arrayGet(k), obj4.isNum()) && (obj5 = obj3.arrayGet(k + 1), obj5.isNum()) && (obj6 = obj3.arrayGet(k + 2), obj6.isNum())) { - widths.excepsV[widths.nExcepsV].first = j; - widths.excepsV[widths.nExcepsV].last = j; - widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001; - widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001; - widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001; + GfxFontCIDWidthExcepV excepV { static_cast(j), static_cast(j), obj4.getNum() * 0.001, obj5.getNum() * 0.001, obj6.getNum() * 0.001 }; + widths.excepsV.push_back(excepV); ++j; - ++widths.nExcepsV; } else { error(errSyntaxError, -1, "Bad widths (W2) array in Type 0 font"); } @@ -1974,7 +1939,7 @@ GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, std::optionaldecRefCnt(); } - gfree(widths.exceps); - gfree(widths.excepsV); if (cidToGID) { gfree(cidToGID); } @@ -2036,9 +1999,9 @@ int GfxCIDFont::getNextChar(const char *s, int len, CharCode *code, Unicode cons h = widths.defHeight; vx = getWidth(cid) / 2; vy = widths.defVY; - if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) { + if (widths.excepsV.size() > 0 && cid >= widths.excepsV[0].first) { a = 0; - b = widths.nExcepsV; + b = widths.excepsV.size(); // invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first while (b - a > 1) { m = (a + b) / 2; @@ -2331,9 +2294,9 @@ double GfxCIDFont::getWidth(CID cid) const int a, b, m; w = widths.defWidth; - if (widths.nExceps > 0 && cid >= widths.exceps[0].first) { + if (widths.exceps.size() > 0 && cid >= widths.exceps[0].first) { a = 0; - b = widths.nExceps; + b = widths.exceps.size(); // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first while (b - a > 1) { m = (a + b) / 2; diff --git a/poppler/GfxFont.h b/poppler/GfxFont.h index fbc08de17..2b8f34870 100644 --- a/poppler/GfxFont.h +++ b/poppler/GfxFont.h @@ -97,11 +97,8 @@ struct GfxFontCIDWidths double defWidth; // default char width double defHeight; // default char height double defVY; // default origin position - GfxFontCIDWidthExcep *exceps; // exceptions - int nExceps; // number of valid entries in exceps - GfxFontCIDWidthExcepV * // exceptions for vertical font - excepsV; - int nExcepsV; // number of valid entries in excepsV + std::vector exceps; // exceptions + std::vector excepsV; // exceptions for vertical font }; //------------------------------------------------------------------------ From 1e898d55e66b4c39b2349e17756969fca7762e9f Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 6 Jun 2024 22:55:22 +0200 Subject: [PATCH 03/27] Update (C) --- poppler/GfxFont.cc | 1 + poppler/GfxFont.h | 1 + 2 files changed, 2 insertions(+) diff --git a/poppler/GfxFont.cc b/poppler/GfxFont.cc index 91b798d9a..e1c43e9c1 100644 --- a/poppler/GfxFont.cc +++ b/poppler/GfxFont.cc @@ -38,6 +38,7 @@ // Copyright (C) 2021, 2022, 2024 Oliver Sander // Copyright (C) 2023 Khaled Hosny // Copyright (C) 2024 Nelson Benítez León +// Copyright (C) 2024 g10 Code GmbH, Author: Sune Stolborg Vuorela // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git diff --git a/poppler/GfxFont.h b/poppler/GfxFont.h index 2b8f34870..c4dde6cb5 100644 --- a/poppler/GfxFont.h +++ b/poppler/GfxFont.h @@ -25,6 +25,7 @@ // Copyright (C) 2015 Thomas Freitag // Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, . Work sponsored by the LiMux project of the city of Munich // Copyright (C) 2021, 2022 Oliver Sander +// Copyright (C) 2024 g10 Code GmbH, Author: Sune Stolborg Vuorela // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git From 37fda1d8b7e9d987fc5fa9ca5494c5c796ef4fed Mon Sep 17 00:00:00 2001 From: Pratham Gandhi Date: Thu, 6 Jun 2024 18:19:02 +0530 Subject: [PATCH 04/27] Handled the additional document actions in qt frontends --- qt5/src/poppler-document.cc | 31 +++++++++++++++++++++++++++++++ qt5/src/poppler-qt5.h | 25 +++++++++++++++++++++++++ qt6/src/poppler-document.cc | 30 ++++++++++++++++++++++++++++++ qt6/src/poppler-qt6.h | 25 +++++++++++++++++++++++++ 4 files changed, 111 insertions(+) diff --git a/qt5/src/poppler-document.cc b/qt5/src/poppler-document.cc index 6daed6983..bae6b728c 100644 --- a/qt5/src/poppler-document.cc +++ b/qt5/src/poppler-document.cc @@ -770,6 +770,37 @@ OptContentModel *Document::optionalContentModel() return (OptContentModel *)m_doc->m_optContentModel; } +Link *Document::additionalAction(DocumentAdditionalActionsType type) const +{ + Catalog::DocumentAdditionalActionsType actionType; + switch (type) { + case CloseDocument: + actionType = Catalog::actionCloseDocument; + break; + case SaveDocumentStart: + actionType = Catalog::actionSaveDocumentStart; + break; + case SaveDocumentFinish: + actionType = Catalog::actionSaveDocumentFinish; + break; + case PrintDocumentStart: + actionType = Catalog::actionPrintDocumentStart; + break; + case PrintDocumentFinish: + actionType = Catalog::actionPrintDocumentFinish; + break; + default: + return {}; + } + + Link *action = nullptr; + if (std::unique_ptr<::LinkAction> act = m_doc->doc->getCatalog()->getAdditionalAction(actionType)) { + action = PageData::convertLinkActionToLink(act.get(), m_doc, QRectF()); + } + + return action; +} + QStringList Document::scripts() const { Catalog *catalog = m_doc->doc->getCatalog(); diff --git a/qt5/src/poppler-qt5.h b/qt5/src/poppler-qt5.h index 4236de06e..f1cdb7c0c 100644 --- a/qt5/src/poppler-qt5.h +++ b/qt5/src/poppler-qt5.h @@ -1879,6 +1879,31 @@ QString subject = m_doc->info("Subject"); */ QStringList scripts() const; + /** + Describes the flags for additional document actions i.e. + for executing document scripts at different events. + This flag is used by additionalAction method to return the + particular Link. + + \since 24.07 + */ + enum DocumentAdditionalActionsType + { + CloseDocument, ///< Performed before closing the document + SaveDocumentStart, ///< Performed before saving the document + SaveDocumentFinish, ///< Performed after saving the document + PrintDocumentStart, ///< Performed before printing the document + PrintDocumentFinish, ///< Performed after printing the document + }; + + /** + Returns the additional action of the given @p type for the document or + @c 0 if no action has been defined. + + \since 24.07 + */ + Link *additionalAction(DocumentAdditionalActionsType type) const; + /** The PDF identifiers. diff --git a/qt6/src/poppler-document.cc b/qt6/src/poppler-document.cc index 57c70e597..ef35cbbde 100644 --- a/qt6/src/poppler-document.cc +++ b/qt6/src/poppler-document.cc @@ -756,6 +756,36 @@ QStringList Document::scripts() const return scripts; } +std::unique_ptr Document::additionalAction(DocumentAdditionalActionsType type) const +{ + Catalog::DocumentAdditionalActionsType actionType; + switch (type) { + case CloseDocument: + actionType = Catalog::actionCloseDocument; + break; + case SaveDocumentStart: + actionType = Catalog::actionSaveDocumentStart; + break; + case SaveDocumentFinish: + actionType = Catalog::actionSaveDocumentFinish; + break; + case PrintDocumentStart: + actionType = Catalog::actionPrintDocumentStart; + break; + case PrintDocumentFinish: + actionType = Catalog::actionPrintDocumentFinish; + break; + default: + return {}; + } + + if (std::unique_ptr<::LinkAction> act = m_doc->doc->getCatalog()->getAdditionalAction(actionType)) { + return PageData::convertLinkActionToLink(act.get(), m_doc, QRectF()); + } + + return {}; +} + bool Document::getPdfId(QByteArray *permanentId, QByteArray *updateId) const { GooString gooPermanentId; diff --git a/qt6/src/poppler-qt6.h b/qt6/src/poppler-qt6.h index f12bc030c..995a32afa 100644 --- a/qt6/src/poppler-qt6.h +++ b/qt6/src/poppler-qt6.h @@ -1680,6 +1680,31 @@ QString subject = m_doc->info("Subject"); */ QStringList scripts() const; + /** + Describes the flags for additional document actions i.e. + for executing document scripts at different events. + This flag is used by additionalAction method to return the + particular Link. + + \since 24.07 + */ + enum DocumentAdditionalActionsType + { + CloseDocument, ///< Performed before closing the document + SaveDocumentStart, ///< Performed before saving the document + SaveDocumentFinish, ///< Performed after saving the document + PrintDocumentStart, ///< Performed before printing the document + PrintDocumentFinish, ///< Performed after printing the document + }; + + /** + Returns the additional action of the given @p type for the document or + @c 0 if no action has been defined. + + \since 24.07 + */ + std::unique_ptr additionalAction(DocumentAdditionalActionsType type) const; + /** The PDF identifiers. From 912b1d5c583677e2629a0a2c4623baa324adb62b Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Mon, 10 Jun 2024 11:16:29 +0200 Subject: [PATCH 05/27] Remove unused GfxImageColorMap::copy --- poppler/GfxState.cc | 54 +-------------------------------------------- poppler/GfxState.h | 7 +----- 2 files changed, 2 insertions(+), 59 deletions(-) diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc index 0c770f1ca..44f9bbbb7 100644 --- a/poppler/GfxState.cc +++ b/poppler/GfxState.cc @@ -16,7 +16,7 @@ // Copyright (C) 2005 Kristian Høgsberg // Copyright (C) 2006, 2007 Jeff Muizelaar // Copyright (C) 2006, 2010 Carlos Garcia Campos -// Copyright (C) 2006-2022 Albert Astals Cid +// Copyright (C) 2006-2022, 2024 Albert Astals Cid // Copyright (C) 2009, 2012 Koji Otani // Copyright (C) 2009, 2011-2016, 2020, 2023 Thomas Freitag // Copyright (C) 2009, 2019 Christian Persch @@ -5740,58 +5740,6 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *col ok = false; } -GfxImageColorMap::GfxImageColorMap(const GfxImageColorMap *colorMap) -{ - int n, i, k; - - colorSpace = colorMap->colorSpace->copy(); - bits = colorMap->bits; - nComps = colorMap->nComps; - nComps2 = colorMap->nComps2; - useMatte = colorMap->useMatte; - matteColor = colorMap->matteColor; - colorSpace2 = nullptr; - for (k = 0; k < gfxColorMaxComps; ++k) { - lookup[k] = nullptr; - lookup2[k] = nullptr; - } - byte_lookup = nullptr; - n = 1 << bits; - for (k = 0; k < nComps; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); - memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); - } - if (colorSpace->getMode() == csIndexed) { - colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase(); - for (k = 0; k < nComps2; ++k) { - lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); - memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp)); - } - } else if (colorSpace->getMode() == csSeparation) { - colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt(); - for (k = 0; k < nComps2; ++k) { - lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); - memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp)); - } - } else { - for (k = 0; k < nComps; ++k) { - lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); - memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp)); - } - } - if (colorMap->byte_lookup) { - int nc = colorSpace2 ? nComps2 : nComps; - - byte_lookup = (unsigned char *)gmallocn(n, nc); - memcpy(byte_lookup, colorMap->byte_lookup, n * nc); - } - for (i = 0; i < nComps; ++i) { - decodeLow[i] = colorMap->decodeLow[i]; - decodeRange[i] = colorMap->decodeRange[i]; - } - ok = true; -} - GfxImageColorMap::~GfxImageColorMap() { int i; diff --git a/poppler/GfxState.h b/poppler/GfxState.h index 9cf1afc19..8fbc1687f 100644 --- a/poppler/GfxState.h +++ b/poppler/GfxState.h @@ -17,7 +17,7 @@ // Copyright (C) 2006, 2007 Jeff Muizelaar // Copyright (C) 2006 Carlos Garcia Campos // Copyright (C) 2009 Koji Otani -// Copyright (C) 2009-2011, 2013, 2016-2022 Albert Astals Cid +// Copyright (C) 2009-2011, 2013, 2016-2022, 2024 Albert Astals Cid // Copyright (C) 2010 Christian Feuersänger // Copyright (C) 2011 Andrea Canciani // Copyright (C) 2011-2014, 2016, 2020 Thomas Freitag @@ -1203,9 +1203,6 @@ class POPPLER_PRIVATE_EXPORT GfxImageColorMap GfxImageColorMap(const GfxImageColorMap &) = delete; GfxImageColorMap &operator=(const GfxImageColorMap &) = delete; - // Return a copy of this color map. - GfxImageColorMap *copy() const { return new GfxImageColorMap(this); } - // Is color map valid? bool isOk() const { return ok; } @@ -1246,8 +1243,6 @@ class POPPLER_PRIVATE_EXPORT GfxImageColorMap const GfxColor *getMatteColor() const { return (useMatte) ? &matteColor : nullptr; } private: - explicit GfxImageColorMap(const GfxImageColorMap *colorMap); - GfxColorSpace *colorSpace; // the image color space int bits; // bits per component int nComps; // number of components in a pixel From 0554731052d1a97745cb179ab0d45620589dd9c4 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 7 Jun 2024 00:54:55 +0200 Subject: [PATCH 06/27] pdfinfo: Fix crash in broken documents when using -dests --- utils/pdfinfo.cc | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/utils/pdfinfo.cc b/utils/pdfinfo.cc index 5d37ef64f..7d569749b 100644 --- a/utils/pdfinfo.cc +++ b/utils/pdfinfo.cc @@ -15,7 +15,7 @@ // under GPL version 2 or later // // Copyright (C) 2006 Dom Lachowicz -// Copyright (C) 2007-2010, 2012, 2016-2022 Albert Astals Cid +// Copyright (C) 2007-2010, 2012, 2016-2022, 2024 Albert Astals Cid // Copyright (C) 2010 Hib Eris // Copyright (C) 2011 Vittal Aithal // Copyright (C) 2012, 2013, 2016-2018, 2021 Adrian Johnson @@ -113,16 +113,21 @@ static const ArgDesc argDesc[] = { { "-f", argInt, &firstPage, 0, "first page to { "-?", argFlag, &printHelp, 0, "print usage information" }, {} }; -static void printTextString(const GooString *s, const UnicodeMap *uMap) +static void printStdTextString(const std::string &s, const UnicodeMap *uMap) { char buf[8]; - std::vector u = TextStringToUCS4(s->toStr()); + const std::vector u = TextStringToUCS4(s); for (const auto &c : u) { int n = uMap->mapUnicode(c, buf, sizeof(buf)); fwrite(buf, 1, n, stdout); } } +static void printTextString(const GooString *s, const UnicodeMap *uMap) +{ + printStdTextString(s->toStr(), uMap); +} + static void printUCS4String(const Unicode *u, int len, const UnicodeMap *uMap) { char buf[8]; @@ -294,11 +299,6 @@ static void printStruct(const StructElement *element, unsigned indent) } } -struct GooStringCompare -{ - bool operator()(GooString *lhs, GooString *rhs) const { return lhs->cmp(const_cast(rhs)) < 0; } -}; - static void printLinkDest(const std::unique_ptr &dest) { GooString s; @@ -369,29 +369,25 @@ static void printLinkDest(const std::unique_ptr &dest) static void printDestinations(PDFDoc *doc, const UnicodeMap *uMap) { - std::map, GooStringCompare>> map; + std::map>> map; int numDests = doc->getCatalog()->numDestNameTree(); for (int i = 0; i < numDests; i++) { - GooString *name = new GooString(doc->getCatalog()->getDestNameTreeName(i)); + const GooString *name = doc->getCatalog()->getDestNameTreeName(i); std::unique_ptr dest = doc->getCatalog()->getDestNameTreeDest(i); - if (dest && dest->isPageRef()) { + if (name && dest && dest->isPageRef()) { Ref pageRef = dest->getPageRef(); - map[pageRef].insert(std::make_pair(name, std::move(dest))); - } else { - delete name; + map[pageRef].insert(std::make_pair(name->toStr(), std::move(dest))); } } numDests = doc->getCatalog()->numDests(); for (int i = 0; i < numDests; i++) { - GooString *name = new GooString(doc->getCatalog()->getDestsName(i)); + const char *name = doc->getCatalog()->getDestsName(i); std::unique_ptr dest = doc->getCatalog()->getDestsDest(i); - if (dest && dest->isPageRef()) { + if (name && dest && dest->isPageRef()) { Ref pageRef = dest->getPageRef(); map[pageRef].insert(std::make_pair(name, std::move(dest))); - } else { - delete name; } } @@ -405,9 +401,8 @@ static void printDestinations(PDFDoc *doc, const UnicodeMap *uMap) printf("%4d ", i); printLinkDest(it.second); printf(" \""); - printTextString(it.first, uMap); + printStdTextString(it.first, uMap); printf("\"\n"); - delete it.first; } } } From 77457e1350720d197d1b2e879aa9bf11a0d575d2 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Tue, 11 Jun 2024 22:09:31 +0200 Subject: [PATCH 07/27] Revert "Remove unused GfxImageColorMap::copy" kitinerary uses it This reverts commit 912b1d5c583677e2629a0a2c4623baa324adb62b. --- poppler/GfxState.cc | 54 ++++++++++++++++++++++++++++++++++++++++++++- poppler/GfxState.h | 7 +++++- 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc index 44f9bbbb7..0c770f1ca 100644 --- a/poppler/GfxState.cc +++ b/poppler/GfxState.cc @@ -16,7 +16,7 @@ // Copyright (C) 2005 Kristian Høgsberg // Copyright (C) 2006, 2007 Jeff Muizelaar // Copyright (C) 2006, 2010 Carlos Garcia Campos -// Copyright (C) 2006-2022, 2024 Albert Astals Cid +// Copyright (C) 2006-2022 Albert Astals Cid // Copyright (C) 2009, 2012 Koji Otani // Copyright (C) 2009, 2011-2016, 2020, 2023 Thomas Freitag // Copyright (C) 2009, 2019 Christian Persch @@ -5740,6 +5740,58 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *col ok = false; } +GfxImageColorMap::GfxImageColorMap(const GfxImageColorMap *colorMap) +{ + int n, i, k; + + colorSpace = colorMap->colorSpace->copy(); + bits = colorMap->bits; + nComps = colorMap->nComps; + nComps2 = colorMap->nComps2; + useMatte = colorMap->useMatte; + matteColor = colorMap->matteColor; + colorSpace2 = nullptr; + for (k = 0; k < gfxColorMaxComps; ++k) { + lookup[k] = nullptr; + lookup2[k] = nullptr; + } + byte_lookup = nullptr; + n = 1 << bits; + for (k = 0; k < nComps; ++k) { + lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); + memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); + } + if (colorSpace->getMode() == csIndexed) { + colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase(); + for (k = 0; k < nComps2; ++k) { + lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); + memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp)); + } + } else if (colorSpace->getMode() == csSeparation) { + colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt(); + for (k = 0; k < nComps2; ++k) { + lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); + memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp)); + } + } else { + for (k = 0; k < nComps; ++k) { + lookup2[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); + memcpy(lookup2[k], colorMap->lookup2[k], n * sizeof(GfxColorComp)); + } + } + if (colorMap->byte_lookup) { + int nc = colorSpace2 ? nComps2 : nComps; + + byte_lookup = (unsigned char *)gmallocn(n, nc); + memcpy(byte_lookup, colorMap->byte_lookup, n * nc); + } + for (i = 0; i < nComps; ++i) { + decodeLow[i] = colorMap->decodeLow[i]; + decodeRange[i] = colorMap->decodeRange[i]; + } + ok = true; +} + GfxImageColorMap::~GfxImageColorMap() { int i; diff --git a/poppler/GfxState.h b/poppler/GfxState.h index 8fbc1687f..9cf1afc19 100644 --- a/poppler/GfxState.h +++ b/poppler/GfxState.h @@ -17,7 +17,7 @@ // Copyright (C) 2006, 2007 Jeff Muizelaar // Copyright (C) 2006 Carlos Garcia Campos // Copyright (C) 2009 Koji Otani -// Copyright (C) 2009-2011, 2013, 2016-2022, 2024 Albert Astals Cid +// Copyright (C) 2009-2011, 2013, 2016-2022 Albert Astals Cid // Copyright (C) 2010 Christian Feuersänger // Copyright (C) 2011 Andrea Canciani // Copyright (C) 2011-2014, 2016, 2020 Thomas Freitag @@ -1203,6 +1203,9 @@ class POPPLER_PRIVATE_EXPORT GfxImageColorMap GfxImageColorMap(const GfxImageColorMap &) = delete; GfxImageColorMap &operator=(const GfxImageColorMap &) = delete; + // Return a copy of this color map. + GfxImageColorMap *copy() const { return new GfxImageColorMap(this); } + // Is color map valid? bool isOk() const { return ok; } @@ -1243,6 +1246,8 @@ class POPPLER_PRIVATE_EXPORT GfxImageColorMap const GfxColor *getMatteColor() const { return (useMatte) ? &matteColor : nullptr; } private: + explicit GfxImageColorMap(const GfxImageColorMap *colorMap); + GfxColorSpace *colorSpace; // the image color space int bits; // bits per component int nComps; // number of components in a pixel From b16c379582ef1af6101aaa20e69a9abfd32fad7d Mon Sep 17 00:00:00 2001 From: Sune Vuorela Date: Wed, 12 Jun 2024 14:06:29 +0200 Subject: [PATCH 08/27] FoFiTrueType: less manual memory handling - use vector instead of pointer,length for owning structures - use span instead of pointer,length for non-owning arguments - use std::array for most fixed size arrays - remove gmem usage --- fofi/FoFiTrueType.cc | 184 ++++++++++++++++++------------------------- fofi/FoFiTrueType.h | 12 +-- 2 files changed, 82 insertions(+), 114 deletions(-) diff --git a/fofi/FoFiTrueType.cc b/fofi/FoFiTrueType.cc index 7e177de5f..353cd9b1c 100644 --- a/fofi/FoFiTrueType.cc +++ b/fofi/FoFiTrueType.cc @@ -38,9 +38,9 @@ #include #include #include -#include "goo/gmem.h" #include "goo/GooLikely.h" #include "goo/GooString.h" +#include "goo/GooCheckedOps.h" #include "FoFiType1C.h" #include "FoFiTrueType.h" #include "poppler/Error.h" @@ -109,28 +109,28 @@ struct TrueTypeTable { - unsigned int tag; - unsigned int checksum; - int offset; - int origOffset; - int len; + unsigned int tag = 0; + unsigned int checksum = 0; + int offset = 0; + int origOffset = 0; + int len = 0; }; struct TrueTypeCmap { - int platform; - int encoding; - int offset; - int len; - int fmt; + int platform = 0; + int encoding = 0; + int offset = 0; + int len = 0; + int fmt = 0; }; struct TrueTypeLoca { - int idx; - int origOffset; - int newOffset; - int len; + int idx = 0; + int origOffset = 0; + int newOffset = 0; + int len = 0; }; #define cmapTag 0x636d6170 @@ -482,10 +482,6 @@ std::unique_ptr FoFiTrueType::load(const char *fileName, int faceI FoFiTrueType::FoFiTrueType(const unsigned char *fileA, int lenA, bool freeFileDataA, int faceIndexA) : FoFiBase(fileA, lenA, freeFileDataA) { - tables = nullptr; - nTables = 0; - cmaps = nullptr; - nCmaps = 0; parsedOk = false; faceIndex = faceIndexA; gsubFeatureTable = 0; @@ -494,15 +490,11 @@ FoFiTrueType::FoFiTrueType(const unsigned char *fileA, int lenA, bool freeFileDa parse(); } -FoFiTrueType::~FoFiTrueType() -{ - gfree(tables); - gfree(cmaps); -} +FoFiTrueType::~FoFiTrueType() = default; int FoFiTrueType::getNumCmaps() const { - return nCmaps; + return cmaps.size(); } int FoFiTrueType::getCmapPlatform(int i) const @@ -517,9 +509,7 @@ int FoFiTrueType::getCmapEncoding(int i) const int FoFiTrueType::findCmap(int platform, int encoding) const { - int i; - - for (i = 0; i < nCmaps; ++i) { + for (int i = 0; i < (int)cmaps.size(); ++i) { if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) { return i; } @@ -536,7 +526,7 @@ int FoFiTrueType::mapCodeToGID(int i, unsigned int c) const unsigned int high, low, idx; bool ok; - if (i < 0 || i >= nCmaps) { + if (i < 0 || i >= (int)cmaps.size()) { return 0; } ok = true; @@ -655,12 +645,10 @@ int FoFiTrueType::mapNameToGID(const char *name) const bool FoFiTrueType::getCFFBlock(char **start, int *length) const { - int i; - - if (!openTypeCFF || !tables) { + if (!openTypeCFF || tables.empty()) { return false; } - i = seekTable("CFF "); + int i = seekTable("CFF "); if (i < 0 || !checkRegion(tables[i].offset, tables[i].len)) { return false; } @@ -1055,7 +1043,7 @@ void FoFiTrueType::cvtCharStrings(char **encoding, const int *codeToGID, FoFiOut (*outputFunc)(outputStream, "/.notdef 0 def\n", 15); // if there's no 'cmap' table, punt - if (nCmaps == 0) { + if (cmaps.empty()) { goto err; } @@ -1094,16 +1082,15 @@ void FoFiTrueType::cvtCharStrings(char **encoding, const int *codeToGID, FoFiOut void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const GooString *name, bool needVerticalMetrics, int *maxUsedGlyph) const { - unsigned char headData[54]; - TrueTypeLoca *locaTable; - unsigned char *locaData; + std::array headData; + std::vector locaData; TrueTypeTable newTables[nT42Tables]; unsigned char tableDir[12 + nT42Tables * 16]; bool ok; unsigned int checksum; int nNewTables; - int glyfTableLen, length, pos, glyfPos, i, j, k, vmtxTabLength; - unsigned char vheaTab[36] = { + int glyfTableLen, length, glyfPos, j, k; + std::array vheaTab = { 0, 1, 0, 0, // table version number 0, 0, // ascent 0, 0, // descent @@ -1122,22 +1109,22 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const 0, 0, // metric data format 0, 1 // number of advance heights in vmtx table }; - unsigned char *vmtxTab; + std::vector vmtxTab; bool needVhea, needVmtx; int advance; *maxUsedGlyph = -1; // construct the 'head' table, zero out the font checksum - i = seekTable("head"); - if (i < 0 || i >= nTables) { + int i = seekTable("head"); + if (i < 0 || i >= (int)tables.size()) { return; } - pos = tables[i].offset; + int pos = tables[i].offset; if (!checkRegion(pos, 54)) { return; } - memcpy(headData, file + pos, 54); + memcpy(headData.data(), file + pos, 54); headData[8] = headData[9] = headData[10] = headData[11] = (unsigned char)0; // check for a bogus loca format field in the 'head' table @@ -1154,7 +1141,7 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const // table, cmpTrueTypeLocaOffset uses offset as its primary sort key, // and idx as its secondary key (ensuring that adjacent entries with // the same pos value remain in the same order) - locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca)); + std::vector locaTable { size_t(nGlyphs + 1) }; i = seekTable("loca"); pos = tables[i].offset; i = seekTable("glyf"); @@ -1171,12 +1158,12 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const locaTable[i].origOffset = glyfTableLen; } } - std::sort(locaTable, locaTable + nGlyphs + 1, cmpTrueTypeLocaOffsetFunctor()); + std::sort(locaTable.begin(), locaTable.end(), cmpTrueTypeLocaOffsetFunctor()); for (i = 0; i < nGlyphs; ++i) { locaTable[i].len = locaTable[i + 1].origOffset - locaTable[i].origOffset; } locaTable[nGlyphs].len = 0; - std::sort(locaTable, locaTable + nGlyphs + 1, cmpTrueTypeLocaIdxFunctor()); + std::sort(locaTable.begin(), locaTable.end(), cmpTrueTypeLocaIdxFunctor()); pos = 0; for (i = 0; i <= nGlyphs; ++i) { locaTable[i].newOffset = pos; @@ -1196,7 +1183,7 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const } // construct the new 'loca' table - locaData = (unsigned char *)gmallocn(nGlyphs + 1, (locaFmt ? 4 : 2)); + locaData.resize((nGlyphs + 1) * (locaFmt ? 4 : 2)); for (i = 0; i <= nGlyphs; ++i) { pos = locaTable[i].newOffset; if (locaFmt) { @@ -1217,8 +1204,6 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const ++nNewTables; } } - vmtxTab = nullptr; // make gcc happy - vmtxTabLength = 0; advance = 0; // make gcc happy if (needVerticalMetrics) { needVhea = seekTable("vhea") < 0; @@ -1244,10 +1229,10 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const checksum = 0; // make gcc happy if (i == t42HeadTable) { length = 54; - checksum = computeTableChecksum(headData, 54); + checksum = computeTableChecksum(headData); } else if (i == t42LocaTable) { length = (nGlyphs + 1) * (locaFmt ? 4 : 2); - checksum = computeTableChecksum(locaData, length); + checksum = computeTableChecksum(locaData); } else if (i == t42GlyfTable) { length = 0; checksum = 0; @@ -1258,31 +1243,26 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const length += 4 - (length & 3); } if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) { - checksum += computeTableChecksum(file + glyfPos + locaTable[j].origOffset, locaTable[j].len); + checksum += computeTableChecksum(std::span(file + glyfPos + locaTable[j].origOffset, locaTable[j].len)); } } } else { if ((j = seekTable(t42Tables[i].tag)) >= 0) { length = tables[j].len; if (checkRegion(tables[j].offset, length)) { - checksum = computeTableChecksum(file + tables[j].offset, length); + checksum = computeTableChecksum(std::span(file + tables[j].offset, length)); } } else if (needVerticalMetrics && i == t42VheaTable) { vheaTab[10] = advance / 256; // max advance height vheaTab[11] = advance % 256; - length = sizeof(vheaTab); - checksum = computeTableChecksum(vheaTab, length); + length = vheaTab.size(); + checksum = computeTableChecksum(vheaTab); } else if (needVerticalMetrics && i == t42VmtxTable) { length = 4 + (nGlyphs - 1) * 2; - vmtxTabLength = length; - vmtxTab = (unsigned char *)gmalloc(length); + vmtxTab.resize(length, 0); vmtxTab[0] = advance / 256; vmtxTab[1] = advance % 256; - for (j = 2; j < length; j += 2) { - vmtxTab[j] = 0; - vmtxTab[j + 1] = 0; - } - checksum = computeTableChecksum(vmtxTab, length); + checksum = computeTableChecksum(vmtxTab); } else if (t42Tables[i].required) { //~ error(-1, "Embedded TrueType font is missing a required table ('%s')", //~ t42Tables[i].tag); @@ -1347,7 +1327,7 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const } // compute the font checksum and store it in the head table - checksum = computeTableChecksum(tableDir, 12 + nNewTables * 16); + checksum = computeTableChecksum(std::span(tableDir, 12 + nNewTables * 16)); for (i = 0; i < nNewTables; ++i) { checksum += newTables[i].checksum; } @@ -1367,20 +1347,20 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const } // write the table directory - dumpString(tableDir, 12 + nNewTables * 16, outputFunc, outputStream); + dumpString(std::span(tableDir, 12 + nNewTables * 16), outputFunc, outputStream); // write the tables for (i = 0; i < nNewTables; ++i) { if (i == t42HeadTable) { - dumpString(headData, 54, outputFunc, outputStream); + dumpString(headData, outputFunc, outputStream); } else if (i == t42LocaTable) { length = (nGlyphs + 1) * (locaFmt ? 4 : 2); - dumpString(locaData, length, outputFunc, outputStream); + dumpString(locaData, outputFunc, outputStream); } else if (i == t42GlyfTable) { glyfPos = tables[seekTable("glyf")].offset; for (j = 0; j < nGlyphs; ++j) { if (locaTable[j].len > 0 && checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) { - dumpString(file + glyfPos + locaTable[j].origOffset, locaTable[j].len, outputFunc, outputStream); + dumpString(std::span(file + glyfPos + locaTable[j].origOffset, locaTable[j].len), outputFunc, outputStream); } } } else { @@ -1389,19 +1369,18 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const // headers if ((length = newTables[i].len) > 0) { if ((j = seekTable(t42Tables[i].tag)) >= 0 && checkRegion(tables[j].offset, tables[j].len)) { - dumpString(file + tables[j].offset, tables[j].len, outputFunc, outputStream); + dumpString(std::span(file + tables[j].offset, tables[j].len), outputFunc, outputStream); } else if (needVerticalMetrics && i == t42VheaTable) { if (unlikely(length > (int)sizeof(vheaTab))) { error(errSyntaxWarning, -1, "length bigger than vheaTab size"); length = sizeof(vheaTab); } - dumpString(vheaTab, length, outputFunc, outputStream); + dumpString(vheaTab, outputFunc, outputStream); } else if (needVerticalMetrics && i == t42VmtxTable) { - if (unlikely(length > vmtxTabLength)) { + if (unlikely(length > (int)vmtxTab.size())) { error(errSyntaxWarning, -1, "length bigger than vmtxTab size"); - length = vmtxTabLength; } - dumpString(vmtxTab, length, outputFunc, outputStream); + dumpString(vmtxTab, outputFunc, outputStream); } } } @@ -1409,33 +1388,25 @@ void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const // end the sfnts array (*outputFunc)(outputStream, "] def\n", 6); - - gfree(locaData); - gfree(locaTable); - if (vmtxTab) { - gfree(vmtxTab); - } } -void FoFiTrueType::dumpString(const unsigned char *s, int length, FoFiOutputFunc outputFunc, void *outputStream) const +void FoFiTrueType::dumpString(std::span s, FoFiOutputFunc outputFunc, void *outputStream) { - int pad, i, j; - (*outputFunc)(outputStream, "<", 1); - for (i = 0; i < length; i += 32) { - for (j = 0; j < 32 && i + j < length; ++j) { + for (int i = 0; i < (int)s.size(); i += 32) { + for (int j = 0; j < 32 && i + j < (int)s.size(); ++j) { const std::string buf = GooString::format("{0:02x}", s[i + j] & 0xff); (*outputFunc)(outputStream, buf.c_str(), buf.size()); } if (i % (65536 - 32) == 65536 - 64) { (*outputFunc)(outputStream, ">\n<", 3); - } else if (i + 32 < length) { + } else if (i + 32 < (int)s.size()) { (*outputFunc)(outputStream, "\n", 1); } } - if (length & 3) { - pad = 4 - (length & 3); - for (i = 0; i < pad; ++i) { + if (s.size() & 3) { + int pad = 4 - (s.size() & 3); + for (int i = 0; i < pad; ++i) { (*outputFunc)(outputStream, "00", 2); } } @@ -1443,20 +1414,17 @@ void FoFiTrueType::dumpString(const unsigned char *s, int length, FoFiOutputFunc (*outputFunc)(outputStream, "00>\n", 4); } -unsigned int FoFiTrueType::computeTableChecksum(const unsigned char *data, int length) const +unsigned int FoFiTrueType::computeTableChecksum(std::span data) { - unsigned int checksum, word; - int i; - - checksum = 0; - for (i = 0; i + 3 < length; i += 4) { - word = ((data[i] & 0xff) << 24) + ((data[i + 1] & 0xff) << 16) + ((data[i + 2] & 0xff) << 8) + (data[i + 3] & 0xff); + unsigned checksum = 0; + for (size_t i = 0; i + 3 < data.size(); i += 4) { + unsigned int word = ((data[i] & 0xff) << 24) + ((data[i + 1] & 0xff) << 16) + ((data[i + 2] & 0xff) << 8) + (data[i + 3] & 0xff); checksum += word; } - if (length & 3) { - word = 0; - i = length & ~3; - switch (length & 3) { + if (data.size() & 3) { + unsigned int word = 0; + int i = data.size() & ~3; + switch (data.size() & 3) { case 3: word |= (data[i + 2] & 0xff) << 8; // fallthrough @@ -1516,11 +1484,11 @@ void FoFiTrueType::parse() openTypeCFF = ver == 0x4f54544f; // 'OTTO' // read the table directory - nTables = getU16BE(pos + 4, &parsedOk); + int nTables = getU16BE(pos + 4, &parsedOk); if (!parsedOk) { return; } - tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable)); + tables.resize(nTables); pos += 12; j = 0; for (i = 0; i < nTables; ++i) { @@ -1537,9 +1505,9 @@ void FoFiTrueType::parse() } if (nTables != j) { nTables = j; - tables = (TrueTypeTable *)greallocn_checkoverflow(tables, nTables, sizeof(TrueTypeTable)); + tables.resize(nTables); } - if (!parsedOk || tables == nullptr) { + if (!parsedOk || tables.empty()) { parsedOk = false; return; } @@ -1554,12 +1522,12 @@ void FoFiTrueType::parse() // read the cmaps if ((i = seekTable("cmap")) >= 0) { pos = tables[i].offset + 2; - nCmaps = getU16BE(pos, &parsedOk); + int nCmaps = getU16BE(pos, &parsedOk); pos += 2; if (!parsedOk) { return; } - cmaps = (TrueTypeCmap *)gmallocn(nCmaps, sizeof(TrueTypeCmap)); + cmaps.resize(nCmaps); for (j = 0; j < nCmaps; ++j) { cmaps[j].platform = getU16BE(pos, &parsedOk); cmaps[j].encoding = getU16BE(pos + 2, &parsedOk); @@ -1569,10 +1537,11 @@ void FoFiTrueType::parse() cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk); } if (!parsedOk) { + cmaps.clear(); return; } } else { - nCmaps = 0; + cmaps.clear(); } // get the number of glyphs from the maxp table @@ -1676,10 +1645,9 @@ void FoFiTrueType::readPostTable() int FoFiTrueType::seekTable(const char *tag) const { unsigned int tagI; - int i; tagI = ((tag[0] & 0xff) << 24) | ((tag[1] & 0xff) << 16) | ((tag[2] & 0xff) << 8) | (tag[3] & 0xff); - for (i = 0; i < nTables; ++i) { + for (int i = 0; i < (int)tables.size(); ++i) { if (tables[i].tag == tagI) { return i; } diff --git a/fofi/FoFiTrueType.h b/fofi/FoFiTrueType.h index f98244acc..9edf691e3 100644 --- a/fofi/FoFiTrueType.h +++ b/fofi/FoFiTrueType.h @@ -31,8 +31,10 @@ #include #include +#include #include #include +#include #include "FoFiBase.h" #include "poppler_private_export.h" @@ -160,8 +162,8 @@ class POPPLER_PRIVATE_EXPORT FoFiTrueType : public FoFiBase void cvtEncoding(char **encoding, FoFiOutputFunc outputFunc, void *outputStream) const; void cvtCharStrings(char **encoding, const int *codeToGID, FoFiOutputFunc outputFunc, void *outputStream) const; void cvtSfnts(FoFiOutputFunc outputFunc, void *outputStream, const GooString *name, bool needVerticalMetrics, int *maxUsedGlyph) const; - void dumpString(const unsigned char *s, int length, FoFiOutputFunc outputFunc, void *outputStream) const; - unsigned int computeTableChecksum(const unsigned char *data, int length) const; + static void dumpString(std::span s, FoFiOutputFunc outputFunc, void *outputStream); + static unsigned int computeTableChecksum(std::span data); void parse(); void readPostTable(); int seekTable(const char *tag) const; @@ -171,10 +173,8 @@ class POPPLER_PRIVATE_EXPORT FoFiTrueType : public FoFiBase unsigned int scanLookupSubTable(unsigned int subTable, unsigned int orgGID); int checkGIDInCoverage(unsigned int coverage, unsigned int orgGID); - TrueTypeTable *tables; - int nTables; - TrueTypeCmap *cmaps; - int nCmaps; + std::vector tables; + std::vector cmaps; int nGlyphs; int locaFmt; int bbox[4]; From 753217915013a6e0e19e83872082cda1193e5f50 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Wed, 12 Jun 2024 23:02:16 +0200 Subject: [PATCH 09/27] Update (C) --- fofi/FoFiTrueType.cc | 1 + fofi/FoFiTrueType.h | 1 + 2 files changed, 2 insertions(+) diff --git a/fofi/FoFiTrueType.cc b/fofi/FoFiTrueType.cc index 353cd9b1c..276cb9392 100644 --- a/fofi/FoFiTrueType.cc +++ b/fofi/FoFiTrueType.cc @@ -26,6 +26,7 @@ // Copyright (C) 2018 Adam Reichold // Copyright (C) 2022 Zachary Travis // Copyright (C) 2022, 2024 Oliver Sander +// Copyright (C) 2024 g10 Code GmbH, Author: Sune Stolborg Vuorela // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git diff --git a/fofi/FoFiTrueType.h b/fofi/FoFiTrueType.h index 9edf691e3..4c464b9da 100644 --- a/fofi/FoFiTrueType.h +++ b/fofi/FoFiTrueType.h @@ -20,6 +20,7 @@ // Copyright (C) 2016 William Bader // Copyright (C) 2018 Adam Reichold // Copyright (C) 2022 Oliver Sander +// Copyright (C) 2024 g10 Code GmbH, Author: Sune Stolborg Vuorela // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git From 3f7ed54dc7572504c8148a2cc1d2a13b0298b5df Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Wed, 12 Jun 2024 23:15:17 +0200 Subject: [PATCH 10/27] Forgot to increase the SOVERSION for 24.06.0 (cherry picked from commit 10914f82cee06ea95ace19c5d74a2c2ff2bab4dc) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 66c526d9a..84daea498 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -614,7 +614,7 @@ ADD_GPERF_FILE(TimesItalicWidths) ADD_GPERF_FILE(TimesRomanWidths) ADD_GPERF_FILE(ZapfDingbatsWidths) -set(POPPLER_SOVERSION_NUMBER "137") +set(POPPLER_SOVERSION_NUMBER "138") set(LINKER_SCRIPT "${CMAKE_BINARY_DIR}/libpoppler.map") configure_file( From 1f657b4b5ad392762ec7685198f117f682044f53 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 13 Jun 2024 16:04:07 +0200 Subject: [PATCH 11/27] glib-mkenums is required So fail on cmake stage rather than on compile stage --- glib/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glib/CMakeLists.txt b/glib/CMakeLists.txt index df7992929..4fcf973f0 100644 --- a/glib/CMakeLists.txt +++ b/glib/CMakeLists.txt @@ -38,7 +38,7 @@ set(poppler_glib_public_headers poppler-structure-element.h ) -find_program(GLIB2_MKENUMS glib-mkenums) +find_program(GLIB2_MKENUMS glib-mkenums REQUIRED) find_program(GLIB2_MKENUMS_PYTHON NAMES python3 python) add_custom_command( From 274e054591aac4dc45e21bb8b194fd40673ab6b7 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 13 Jun 2024 16:15:23 +0200 Subject: [PATCH 12/27] Also initialize rootGen --- poppler/XRef.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/poppler/XRef.cc b/poppler/XRef.cc index e97a00ccd..d8c66708c 100644 --- a/poppler/XRef.cc +++ b/poppler/XRef.cc @@ -257,6 +257,7 @@ XRef::XRef() : objStrs { 5 } permFlags = defPermFlags; ownerPasswordOk = false; rootNum = -1; + rootGen = -1; strOwner = false; xrefReconstructed = false; encAlgorithm = cryptNone; From 83c22b3a66a188dd9a17a013aa7a9c38e3e87f89 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 13 Jun 2024 16:26:37 +0200 Subject: [PATCH 13/27] glib: fuzz: free doc properly --- glib/tests/fuzzing/doc_attr_fuzzer.cc | 1 + glib/tests/fuzzing/find_text_fuzzer.cc | 2 ++ glib/tests/fuzzing/label_fuzzer.cc | 2 ++ 3 files changed, 5 insertions(+) diff --git a/glib/tests/fuzzing/doc_attr_fuzzer.cc b/glib/tests/fuzzing/doc_attr_fuzzer.cc index 18d3811fb..011b7444e 100644 --- a/glib/tests/fuzzing/doc_attr_fuzzer.cc +++ b/glib/tests/fuzzing/doc_attr_fuzzer.cc @@ -29,5 +29,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) poppler_document_set_title(doc, buf); free(buf); + g_object_unref(doc); return 0; } diff --git a/glib/tests/fuzzing/find_text_fuzzer.cc b/glib/tests/fuzzing/find_text_fuzzer.cc index e7d0ba908..f5dbe5ba0 100644 --- a/glib/tests/fuzzing/find_text_fuzzer.cc +++ b/glib/tests/fuzzing/find_text_fuzzer.cc @@ -19,6 +19,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) npages = poppler_document_get_n_pages(doc); if (npages < 1) { + g_object_unref(doc); return 0; } @@ -35,5 +36,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) g_object_unref(page); } free(buf); + g_object_unref(doc); return 0; } diff --git a/glib/tests/fuzzing/label_fuzzer.cc b/glib/tests/fuzzing/label_fuzzer.cc index 825a57aa4..2e831d371 100644 --- a/glib/tests/fuzzing/label_fuzzer.cc +++ b/glib/tests/fuzzing/label_fuzzer.cc @@ -19,6 +19,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) npages = poppler_document_get_n_pages(doc); if (npages < 1) { + g_object_unref(doc); return 0; } @@ -34,5 +35,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) g_object_unref(page); } free(buf); + g_object_unref(doc); return 0; } From 5399e7695f725744290cfd3e68bc0ca1109638d5 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 13 Jun 2024 14:46:24 +0000 Subject: [PATCH 14/27] glib: fuzz: poppler_page_find_text requirement is that the text is utf8 --- glib/tests/fuzzing/find_text_fuzzer.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/glib/tests/fuzzing/find_text_fuzzer.cc b/glib/tests/fuzzing/find_text_fuzzer.cc index f5dbe5ba0..8f9c45673 100644 --- a/glib/tests/fuzzing/find_text_fuzzer.cc +++ b/glib/tests/fuzzing/find_text_fuzzer.cc @@ -32,7 +32,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) if (!page) { continue; } - poppler_page_find_text(page, buf); + if (g_utf8_validate(buf, -1, NULL)) { + poppler_page_find_text(page, buf); + } g_object_unref(page); } free(buf); From 2c88fdeff5dbbe19a357b604fbd269b31e337088 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 13 Jun 2024 21:39:03 +0200 Subject: [PATCH 15/27] Prevent some more overflows in broken files --- poppler/Stream.h | 11 +++++++++-- splash/Splash.cc | 18 +++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/poppler/Stream.h b/poppler/Stream.h index e225d8f37..b1b8b492b 100644 --- a/poppler/Stream.h +++ b/poppler/Stream.h @@ -15,7 +15,7 @@ // // Copyright (C) 2005 Jeff Muizelaar // Copyright (C) 2008 Julien Rebetez -// Copyright (C) 2008, 2010, 2011, 2016-2022 Albert Astals Cid +// Copyright (C) 2008, 2010, 2011, 2016-2022, 2024 Albert Astals Cid // Copyright (C) 2009 Carlos Garcia Campos // Copyright (C) 2009 Stefan Thomas // Copyright (C) 2010 Hib Eris @@ -173,8 +173,15 @@ class POPPLER_PRIVATE_EXPORT Stream length += readChars; if (readChars == charsToRead) { if (lookChar() != EOF) { - size += sizeIncrement; + if (unlikely(checkedAdd(size, sizeIncrement, &size))) { + error(errInternal, -1, "toUnsignedChars size grew too much"); + return {}; + } charsToRead = sizeIncrement; + if (unlikely(static_cast(size) > buf.max_size())) { + error(errInternal, -1, "toUnsignedChars size grew too much"); + return {}; + } buf.resize(size); } else { continueReading = false; diff --git a/splash/Splash.cc b/splash/Splash.cc index 5b247ece3..86cae2808 100644 --- a/splash/Splash.cc +++ b/splash/Splash.cc @@ -11,7 +11,7 @@ // All changes made under the Poppler project to this file are licensed // under GPL version 2 or later // -// Copyright (C) 2005-2023 Albert Astals Cid +// Copyright (C) 2005-2024 Albert Astals Cid // Copyright (C) 2005 Marco Pesenti Gritti // Copyright (C) 2010-2016 Thomas Freitag // Copyright (C) 2010 Christian Feuersänger @@ -3705,11 +3705,19 @@ SplashError Splash::arbitraryTransformImage(SplashImageSource src, SplashICCTran // compute the scale factors if (splashAbs(mat[0]) >= splashAbs(mat[1])) { - scaledWidth = xMax - xMin; - scaledHeight = yMax - yMin; + if (unlikely(checkedSubtraction(xMax, xMin, &scaledWidth))) { + return splashErrBadArg; + } + if (unlikely(checkedSubtraction(yMax, yMin, &scaledHeight))) { + return splashErrBadArg; + } } else { - scaledWidth = yMax - yMin; - scaledHeight = xMax - xMin; + if (unlikely(checkedSubtraction(yMax, yMin, &scaledWidth))) { + return splashErrBadArg; + } + if (unlikely(checkedSubtraction(xMax, xMin, &scaledHeight))) { + return splashErrBadArg; + } } if (scaledHeight <= 1 || scaledWidth <= 1 || tilingPattern) { if (mat[0] >= 0) { From 8465b523ad9a67fa51d923da7bda7d0209067acb Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 14 Jun 2024 10:14:50 +0200 Subject: [PATCH 16/27] Fix crash when converting invalid utf16 to utf8 --- poppler/UTF.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/poppler/UTF.cc b/poppler/UTF.cc index f8ebb8c84..78dac2c64 100644 --- a/poppler/UTF.cc +++ b/poppler/UTF.cc @@ -432,7 +432,7 @@ int utf16CountUtf8Bytes(const uint16_t *utf16) utf16++; } if (state != UTF8_ACCEPT && state != UTF8_REJECT) { - count++; // replace with REPLACEMENT_CHAR + count += 3; // replace with REPLACEMENT_CHAR } return count; From e6f279ca1db6f6364dd44d46a6d3edf02c98f5b5 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 14 Jun 2024 10:17:11 +0200 Subject: [PATCH 17/27] We have maxUtf8 so pass it along to be safer --- poppler/UTF.cc | 4 ++-- poppler/UTF.h | 2 +- qt5/tests/check_utf_conversion.cpp | 2 +- qt6/tests/check_utf_conversion.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/poppler/UTF.cc b/poppler/UTF.cc index 78dac2c64..2269a3761 100644 --- a/poppler/UTF.cc +++ b/poppler/UTF.cc @@ -487,12 +487,12 @@ int utf16ToUtf8(const uint16_t *utf16, char *utf8, int maxUtf8, int maxUtf16) // Allocate utf8 string and convert utf16 into it. char *utf16ToUtf8(const uint16_t *utf16, int *len) { - int n = utf16CountUtf8Bytes(utf16); + const int n = utf16CountUtf8Bytes(utf16); if (len) { *len = n; } char *utf8 = (char *)gmalloc(n + 1); - utf16ToUtf8(utf16, utf8); + utf16ToUtf8(utf16, utf8, n + 1, INT_MAX); return utf8; } diff --git a/poppler/UTF.h b/poppler/UTF.h index a51e2e317..eaa656be6 100644 --- a/poppler/UTF.h +++ b/poppler/UTF.h @@ -131,7 +131,7 @@ int POPPLER_PRIVATE_EXPORT utf16CountUtf8Bytes(const uint16_t *utf16); // maxUtf16 - maximum number of UTF-16 code units to convert. Conversion stops when // either this count is reached or a null is encountered. // Returns number of UTF-8 bytes written (excluding NULL). -int POPPLER_PRIVATE_EXPORT utf16ToUtf8(const uint16_t *utf16, char *utf8, int maxUtf8 = INT_MAX, int maxUtf16 = INT_MAX); +int POPPLER_PRIVATE_EXPORT utf16ToUtf8(const uint16_t *utf16, char *utf8, int maxUtf8, int maxUtf16); // Allocate utf8 string and convert utf16 into it. char POPPLER_PRIVATE_EXPORT *utf16ToUtf8(const uint16_t *utf16, int *len = nullptr); diff --git a/qt5/tests/check_utf_conversion.cpp b/qt5/tests/check_utf_conversion.cpp index 93bae4afc..e3933e86f 100644 --- a/qt5/tests/check_utf_conversion.cpp +++ b/qt5/tests/check_utf_conversion.cpp @@ -113,7 +113,7 @@ void TestUTFConversion::testUTF() QCOMPARE(len, (int)strlen(str)); Q_ASSERT(len < (int)sizeof(utf8Buf)); // if this fails, make utf8Buf larger - len = utf16ToUtf8(s.utf16(), utf8Buf); + len = utf16ToUtf8(s.utf16(), utf8Buf, sizeof(utf8Buf), INT_MAX); QVERIFY(compare(utf8Buf, str)); QCOMPARE(len, (int)strlen(str)); diff --git a/qt6/tests/check_utf_conversion.cpp b/qt6/tests/check_utf_conversion.cpp index d5fb0e292..943c55398 100644 --- a/qt6/tests/check_utf_conversion.cpp +++ b/qt6/tests/check_utf_conversion.cpp @@ -111,7 +111,7 @@ void TestUTFConversion::testUTF() QCOMPARE(len, (int)strlen(str)); Q_ASSERT(len < (int)sizeof(utf8Buf)); // if this fails, make utf8Buf larger - len = utf16ToUtf8(s.utf16(), utf8Buf); + len = utf16ToUtf8(s.utf16(), utf8Buf, sizeof(utf8Buf), INT_MAX); QVERIFY(compare(utf8Buf, str)); QCOMPARE(len, (int)strlen(str)); From ef439ea30f92bc1cf9dd584e9f7b514e6ec7a240 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Mon, 10 Jun 2024 11:06:34 +0200 Subject: [PATCH 18/27] Make MediaRendition::copy return a unique_ptr --- poppler/Rendition.cc | 6 +++--- poppler/Rendition.h | 4 ++-- qt5/src/poppler-link.cc | 24 +++++++++++++----------- qt5/src/poppler-link.h | 17 +++++++++++++++-- qt5/src/poppler-media.cc | 12 +++++++----- qt5/src/poppler-media.h | 12 ++++++++++-- qt5/src/poppler-page.cc | 4 ++-- qt6/src/poppler-link.cc | 24 +++++++++++++----------- qt6/src/poppler-link.h | 17 +++++++++++++++-- qt6/src/poppler-media.cc | 12 +++++++----- qt6/src/poppler-media.h | 10 ++++++++-- qt6/src/poppler-page.cc | 4 ++-- 12 files changed, 97 insertions(+), 49 deletions(-) diff --git a/poppler/Rendition.cc b/poppler/Rendition.cc index 7ca82ff60..056fb2e19 100644 --- a/poppler/Rendition.cc +++ b/poppler/Rendition.cc @@ -7,7 +7,7 @@ // Pino Toscano (c) 2008 // Carlos Garcia Campos (c) 2010 // Tobias Koenig (c) 2012 -// Albert Astals Cid (C) 2017, 2018 +// Albert Astals Cid (C) 2017, 2018, 2024 // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -407,9 +407,9 @@ void MediaRendition::outputToFile(FILE *fp) } } -MediaRendition *MediaRendition::copy() const +std::unique_ptr MediaRendition::copy() const { - return new MediaRendition(*this); + return std::make_unique(*this); } // TODO: SelectorRendition diff --git a/poppler/Rendition.h b/poppler/Rendition.h index 1a14c39e8..9721abf86 100644 --- a/poppler/Rendition.h +++ b/poppler/Rendition.h @@ -5,7 +5,7 @@ //--------------------------------------------------------------------------------- // Hugo Mercier (c) 2008 // Carlos Garcia Campos (c) 2010 -// Albert Astals Cid (C) 2017, 2018, 2021 +// Albert Astals Cid (C) 2017, 2018, 2021, 2024 // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -140,7 +140,7 @@ class POPPLER_PRIVATE_EXPORT MediaRendition // write embedded stream to file void outputToFile(FILE *); - MediaRendition *copy() const; + std::unique_ptr copy() const; private: bool ok; diff --git a/qt5/src/poppler-link.cc b/qt5/src/poppler-link.cc index cb114eaec..eb841ca55 100644 --- a/qt5/src/poppler-link.cc +++ b/qt5/src/poppler-link.cc @@ -1,5 +1,5 @@ /* poppler-link.cc: qt interface to poppler - * Copyright (C) 2006-2007, 2013, 2016-2021, Albert Astals Cid + * Copyright (C) 2006-2007, 2013, 2016-2021, 2024, Albert Astals Cid * Copyright (C) 2007-2008, Pino Toscano * Copyright (C) 2010 Hib Eris * Copyright (C) 2012, Tobias Koenig @@ -151,17 +151,17 @@ LinkSoundPrivate::~LinkSoundPrivate() class LinkRenditionPrivate : public LinkPrivate { public: - explicit LinkRenditionPrivate(const QRectF &area, ::MediaRendition *rendition, ::LinkRendition::RenditionOperation operation, const QString &script, const Ref ref); + explicit LinkRenditionPrivate(const QRectF &area, std::unique_ptr<::MediaRendition> &&rendition, ::LinkRendition::RenditionOperation operation, const QString &script, const Ref ref); ~LinkRenditionPrivate() override; - MediaRendition *rendition; + std::unique_ptr rendition; LinkRendition::RenditionAction action; QString script; Ref annotationReference; }; -LinkRenditionPrivate::LinkRenditionPrivate(const QRectF &area, ::MediaRendition *r, ::LinkRendition::RenditionOperation operation, const QString &javaScript, const Ref ref) - : LinkPrivate(area), rendition(r ? new MediaRendition(r) : nullptr), action(LinkRendition::PlayRendition), script(javaScript), annotationReference(ref) +LinkRenditionPrivate::LinkRenditionPrivate(const QRectF &area, std::unique_ptr<::MediaRendition> &&r, ::LinkRendition::RenditionOperation operation, const QString &javaScript, const Ref ref) + : LinkPrivate(area), rendition(r ? new MediaRendition(std::move(r)) : nullptr), action(LinkRendition::PlayRendition), script(javaScript), annotationReference(ref) { switch (operation) { case ::LinkRendition::NoRendition: @@ -182,10 +182,7 @@ LinkRenditionPrivate::LinkRenditionPrivate(const QRectF &area, ::MediaRendition } } -LinkRenditionPrivate::~LinkRenditionPrivate() -{ - delete rendition; -} +LinkRenditionPrivate::~LinkRenditionPrivate() = default; class LinkJavaScriptPrivate : public LinkPrivate { @@ -572,7 +569,12 @@ SoundObject *LinkSound::sound() const // LinkRendition LinkRendition::LinkRendition(const QRectF &linkArea, ::MediaRendition *rendition, int operation, const QString &script, const Ref &annotationReference) // clazy:exclude=function-args-by-value - : Link(*new LinkRenditionPrivate(linkArea, rendition, static_cast(operation), script, annotationReference)) + : LinkRendition(linkArea, std::unique_ptr<::MediaRendition>(rendition), operation, script, annotationReference) +{ +} + +LinkRendition::LinkRendition(const QRectF &linkArea, std::unique_ptr<::MediaRendition> &&rendition, int operation, const QString &script, const Ref annotationReference) + : Link(*new LinkRenditionPrivate(linkArea, std::move(rendition), static_cast(operation), script, annotationReference)) { } @@ -586,7 +588,7 @@ Link::LinkType LinkRendition::linkType() const MediaRendition *LinkRendition::rendition() const { Q_D(const LinkRendition); - return d->rendition; + return d->rendition.get(); } LinkRendition::RenditionAction LinkRendition::action() const diff --git a/qt5/src/poppler-link.h b/qt5/src/poppler-link.h index 5de354292..b37e32511 100644 --- a/qt5/src/poppler-link.h +++ b/qt5/src/poppler-link.h @@ -1,5 +1,5 @@ /* poppler-link.h: qt interface to poppler - * Copyright (C) 2006, 2013, 2016, 2018, 2019, 2021, 2022, Albert Astals Cid + * Copyright (C) 2006, 2013, 2016, 2018, 2019, 2021, 2022, 2024, Albert Astals Cid * Copyright (C) 2007-2008, 2010, Pino Toscano * Copyright (C) 2010, 2012, Guillermo Amaral * Copyright (C) 2012, Tobias Koenig @@ -33,6 +33,8 @@ #include #include "poppler-export.h" +#include + struct Ref; class MediaRendition; @@ -499,7 +501,18 @@ class POPPLER_QT5_EXPORT LinkRendition : public Link * \since 0.22 */ // TODO Next ABI break, remove & from annotationReference - LinkRendition(const QRectF &linkArea, ::MediaRendition *rendition, int operation, const QString &script, const Ref &annotationReference); + [[deprecated]] LinkRendition(const QRectF &linkArea, ::MediaRendition *rendition, int operation, const QString &script, const Ref &annotationReference); + + /** + * Create a new rendition link. + * + * \param linkArea the active area of the link + * \param rendition the media rendition object. + * \param operation the numeric operation (action) (@see ::LinkRendition::RenditionOperation) + * \param script the java script code + * \param annotationReference the object reference of the screen annotation associated with this rendition action + */ + LinkRendition(const QRectF &linkArea, std::unique_ptr<::MediaRendition> &&rendition, int operation, const QString &script, const Ref annotationReference); /** * Destructor. diff --git a/qt5/src/poppler-media.cc b/qt5/src/poppler-media.cc index cf634ca29..d3c30b70e 100644 --- a/qt5/src/poppler-media.cc +++ b/qt5/src/poppler-media.cc @@ -1,6 +1,6 @@ /* poppler-media.cc: qt interface to poppler * Copyright (C) 2012 Guillermo A. Amaral B. - * Copyright (C) 2013, 2018, 2021 Albert Astals Cid + * Copyright (C) 2013, 2018, 2021, 2024 Albert Astals Cid * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,17 +32,19 @@ namespace Poppler { class MediaRenditionPrivate { public: - explicit MediaRenditionPrivate(::MediaRendition *renditionA) : rendition(renditionA) { } + explicit MediaRenditionPrivate(std::unique_ptr<::MediaRendition> &&renditionA) : rendition(std::move(renditionA)) { } - ~MediaRenditionPrivate() { delete rendition; } + ~MediaRenditionPrivate() = default; MediaRenditionPrivate(const MediaRenditionPrivate &) = delete; MediaRenditionPrivate &operator=(const MediaRenditionPrivate &) = delete; - ::MediaRendition *rendition; + std::unique_ptr<::MediaRendition> rendition; }; -MediaRendition::MediaRendition(::MediaRendition *rendition) : d_ptr(new MediaRenditionPrivate(rendition)) { } +MediaRendition::MediaRendition(::MediaRendition *rendition) : MediaRendition(std::unique_ptr<::MediaRendition>(rendition)) { } + +MediaRendition::MediaRendition(std::unique_ptr<::MediaRendition> &&rendition) : d_ptr(new MediaRenditionPrivate(std::move(rendition))) { } MediaRendition::~MediaRendition() { diff --git a/qt5/src/poppler-media.h b/qt5/src/poppler-media.h index 7d5fe93d5..cc7638339 100644 --- a/qt5/src/poppler-media.h +++ b/qt5/src/poppler-media.h @@ -1,6 +1,6 @@ /* poppler-media.h: qt interface to poppler * Copyright (C) 2012 Guillermo A. Amaral B. - * Copyright (C) 2012, 2013, 2021 Albert Astals Cid + * Copyright (C) 2012, 2013, 2021, 2024 Albert Astals Cid * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,6 +25,8 @@ #include #include +#include + class MediaRendition; class QIODevice; @@ -42,7 +44,13 @@ class POPPLER_QT5_EXPORT MediaRendition /** Constructs a MediaRendition. Takes ownership of the passed rendition */ - explicit MediaRendition(::MediaRendition *rendition); + [[deprecated]] explicit MediaRendition(::MediaRendition *rendition); + + /** + Constructs a MediaRendition. + */ + explicit MediaRendition(std::unique_ptr<::MediaRendition> &&rendition); + ~MediaRendition(); /** diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc index cb9d17efc..05de82da1 100644 --- a/qt5/src/poppler-page.cc +++ b/qt5/src/poppler-page.cc @@ -1,7 +1,7 @@ /* poppler-page.cc: qt interface to poppler * Copyright (C) 2005, Net Integration Technologies, Inc. * Copyright (C) 2005, Brad Hards - * Copyright (C) 2005-2022, Albert Astals Cid + * Copyright (C) 2005-2022, 2024, Albert Astals Cid * Copyright (C) 2005, Stefan Kebekus * Copyright (C) 2006-2011, Pino Toscano * Copyright (C) 2008 Carlos Garcia Campos @@ -318,7 +318,7 @@ Link *PageData::convertLinkActionToLink(::LinkAction *a, DocumentData *parentDoc reference = lrn->getScreenAnnot(); } - popplerLink = new LinkRendition(linkArea, lrn->getMedia() ? lrn->getMedia()->copy() : nullptr, lrn->getOperation(), UnicodeParsedString(lrn->getScript()), reference); + popplerLink = new LinkRendition(linkArea, lrn->getMedia() ? lrn->getMedia()->copy() : std::unique_ptr<::MediaRendition> {}, lrn->getOperation(), UnicodeParsedString(lrn->getScript()), reference); } break; case actionOCGState: { diff --git a/qt6/src/poppler-link.cc b/qt6/src/poppler-link.cc index deb5a79ac..e85e18255 100644 --- a/qt6/src/poppler-link.cc +++ b/qt6/src/poppler-link.cc @@ -1,5 +1,5 @@ /* poppler-link.cc: qt interface to poppler - * Copyright (C) 2006-2007, 2013, 2016-2021, Albert Astals Cid + * Copyright (C) 2006-2007, 2013, 2016-2021, 2024, Albert Astals Cid * Copyright (C) 2007-2008, Pino Toscano * Copyright (C) 2010 Hib Eris * Copyright (C) 2012, Tobias Koenig @@ -152,17 +152,17 @@ LinkSoundPrivate::~LinkSoundPrivate() class LinkRenditionPrivate : public LinkPrivate { public: - LinkRenditionPrivate(const QRectF &area, ::MediaRendition *rendition, ::LinkRendition::RenditionOperation operation, const QString &script, const Ref ref); + LinkRenditionPrivate(const QRectF &area, std::unique_ptr<::MediaRendition> &&r, ::LinkRendition::RenditionOperation operation, const QString &script, const Ref ref); ~LinkRenditionPrivate() override; - MediaRendition *rendition; + std::unique_ptr rendition; LinkRendition::RenditionAction action; QString script; Ref annotationReference; }; -LinkRenditionPrivate::LinkRenditionPrivate(const QRectF &area, ::MediaRendition *r, ::LinkRendition::RenditionOperation operation, const QString &javaScript, const Ref ref) - : LinkPrivate(area), rendition(r ? new MediaRendition(r) : nullptr), action(LinkRendition::PlayRendition), script(javaScript), annotationReference(ref) +LinkRenditionPrivate::LinkRenditionPrivate(const QRectF &area, std::unique_ptr<::MediaRendition> &&r, ::LinkRendition::RenditionOperation operation, const QString &javaScript, const Ref ref) + : LinkPrivate(area), rendition(r ? new MediaRendition(std::move(r)) : nullptr), action(LinkRendition::PlayRendition), script(javaScript), annotationReference(ref) { switch (operation) { case ::LinkRendition::NoRendition: @@ -183,10 +183,7 @@ LinkRenditionPrivate::LinkRenditionPrivate(const QRectF &area, ::MediaRendition } } -LinkRenditionPrivate::~LinkRenditionPrivate() -{ - delete rendition; -} +LinkRenditionPrivate::~LinkRenditionPrivate() = default; class LinkJavaScriptPrivate : public LinkPrivate { @@ -578,7 +575,12 @@ SoundObject *LinkSound::sound() const // LinkRendition LinkRendition::LinkRendition(const QRectF &linkArea, ::MediaRendition *rendition, int operation, const QString &script, const Ref annotationReference) - : Link(*new LinkRenditionPrivate(linkArea, rendition, static_cast(operation), script, annotationReference)) + : LinkRendition(linkArea, std::unique_ptr<::MediaRendition>(rendition), operation, script, annotationReference) +{ +} + +LinkRendition::LinkRendition(const QRectF &linkArea, std::unique_ptr<::MediaRendition> &&rendition, int operation, const QString &script, const Ref annotationReference) + : Link(*new LinkRenditionPrivate(linkArea, std::move(rendition), static_cast(operation), script, annotationReference)) { } @@ -592,7 +594,7 @@ Link::LinkType LinkRendition::linkType() const MediaRendition *LinkRendition::rendition() const { Q_D(const LinkRendition); - return d->rendition; + return d->rendition.get(); } LinkRendition::RenditionAction LinkRendition::action() const diff --git a/qt6/src/poppler-link.h b/qt6/src/poppler-link.h index 52065a2e6..9e117fd98 100644 --- a/qt6/src/poppler-link.h +++ b/qt6/src/poppler-link.h @@ -1,5 +1,5 @@ /* poppler-link.h: qt interface to poppler - * Copyright (C) 2006, 2013, 2016, 2018, 2019, 2021, 2022, Albert Astals Cid + * Copyright (C) 2006, 2013, 2016, 2018, 2019, 2021, 2022, 2024, Albert Astals Cid * Copyright (C) 2007-2008, 2010, Pino Toscano * Copyright (C) 2010, 2012, Guillermo Amaral * Copyright (C) 2012, Tobias Koenig @@ -33,6 +33,8 @@ #include #include "poppler-export.h" +#include + struct Ref; class MediaRendition; @@ -488,7 +490,18 @@ class POPPLER_QT6_EXPORT LinkRendition : public Link * \param script the java script code * \param annotationReference the object reference of the screen annotation associated with this rendition action */ - LinkRendition(const QRectF &linkArea, ::MediaRendition *rendition, int operation, const QString &script, const Ref annotationReference); + [[deprecated]] LinkRendition(const QRectF &linkArea, ::MediaRendition *rendition, int operation, const QString &script, const Ref annotationReference); + + /** + * Create a new rendition link. + * + * \param linkArea the active area of the link + * \param rendition the media rendition object. + * \param operation the numeric operation (action) (@see ::LinkRendition::RenditionOperation) + * \param script the java script code + * \param annotationReference the object reference of the screen annotation associated with this rendition action + */ + LinkRendition(const QRectF &linkArea, std::unique_ptr<::MediaRendition> &&rendition, int operation, const QString &script, const Ref annotationReference); /** * Destructor. diff --git a/qt6/src/poppler-media.cc b/qt6/src/poppler-media.cc index cf634ca29..d3c30b70e 100644 --- a/qt6/src/poppler-media.cc +++ b/qt6/src/poppler-media.cc @@ -1,6 +1,6 @@ /* poppler-media.cc: qt interface to poppler * Copyright (C) 2012 Guillermo A. Amaral B. - * Copyright (C) 2013, 2018, 2021 Albert Astals Cid + * Copyright (C) 2013, 2018, 2021, 2024 Albert Astals Cid * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -32,17 +32,19 @@ namespace Poppler { class MediaRenditionPrivate { public: - explicit MediaRenditionPrivate(::MediaRendition *renditionA) : rendition(renditionA) { } + explicit MediaRenditionPrivate(std::unique_ptr<::MediaRendition> &&renditionA) : rendition(std::move(renditionA)) { } - ~MediaRenditionPrivate() { delete rendition; } + ~MediaRenditionPrivate() = default; MediaRenditionPrivate(const MediaRenditionPrivate &) = delete; MediaRenditionPrivate &operator=(const MediaRenditionPrivate &) = delete; - ::MediaRendition *rendition; + std::unique_ptr<::MediaRendition> rendition; }; -MediaRendition::MediaRendition(::MediaRendition *rendition) : d_ptr(new MediaRenditionPrivate(rendition)) { } +MediaRendition::MediaRendition(::MediaRendition *rendition) : MediaRendition(std::unique_ptr<::MediaRendition>(rendition)) { } + +MediaRendition::MediaRendition(std::unique_ptr<::MediaRendition> &&rendition) : d_ptr(new MediaRenditionPrivate(std::move(rendition))) { } MediaRendition::~MediaRendition() { diff --git a/qt6/src/poppler-media.h b/qt6/src/poppler-media.h index 83bd32942..f794b5595 100644 --- a/qt6/src/poppler-media.h +++ b/qt6/src/poppler-media.h @@ -1,6 +1,6 @@ /* poppler-media.h: qt interface to poppler * Copyright (C) 2012 Guillermo A. Amaral B. - * Copyright (C) 2012, 2013, 2021 Albert Astals Cid + * Copyright (C) 2012, 2013, 2021, 2024 Albert Astals Cid * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -40,7 +40,13 @@ class POPPLER_QT6_EXPORT MediaRendition /** Constructs a MediaRendition. Takes ownership of the passed rendition */ - explicit MediaRendition(::MediaRendition *rendition); + [[deprecated]] explicit MediaRendition(::MediaRendition *rendition); + + /** + Constructs a MediaRendition. + */ + explicit MediaRendition(std::unique_ptr<::MediaRendition> &&rendition); + ~MediaRendition(); /** diff --git a/qt6/src/poppler-page.cc b/qt6/src/poppler-page.cc index 9a0b2c7ea..6a8446321 100644 --- a/qt6/src/poppler-page.cc +++ b/qt6/src/poppler-page.cc @@ -1,7 +1,7 @@ /* poppler-page.cc: qt interface to poppler * Copyright (C) 2005, Net Integration Technologies, Inc. * Copyright (C) 2005, Brad Hards - * Copyright (C) 2005-2022, Albert Astals Cid + * Copyright (C) 2005-2022, 2024, Albert Astals Cid * Copyright (C) 2005, Stefan Kebekus * Copyright (C) 2006-2011, Pino Toscano * Copyright (C) 2008 Carlos Garcia Campos @@ -317,7 +317,7 @@ std::unique_ptr PageData::convertLinkActionToLink(::LinkAction *a, Documen reference = lrn->getScreenAnnot(); } - popplerLink = std::make_unique(linkArea, lrn->getMedia() ? lrn->getMedia()->copy() : nullptr, lrn->getOperation(), UnicodeParsedString(lrn->getScript()), reference); + popplerLink = std::make_unique(linkArea, lrn->getMedia() ? lrn->getMedia()->copy() : std::unique_ptr<::MediaRendition> {}, lrn->getOperation(), UnicodeParsedString(lrn->getScript()), reference); } break; case actionOCGState: { From 4551469474b665dbd3159b526b3998a9acf08542 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Sat, 15 Jun 2024 12:01:25 +0200 Subject: [PATCH 19/27] glib: fuzz: Free memory --- glib/tests/fuzzing/find_text_fuzzer.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/glib/tests/fuzzing/find_text_fuzzer.cc b/glib/tests/fuzzing/find_text_fuzzer.cc index 8f9c45673..1db5d7a76 100644 --- a/glib/tests/fuzzing/find_text_fuzzer.cc +++ b/glib/tests/fuzzing/find_text_fuzzer.cc @@ -10,6 +10,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) PopplerPage *page; char *buf; int npages; + GList *matches; doc = poppler_document_new_from_data((char *)data, size, NULL, &err); if (doc == NULL) { @@ -33,7 +34,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) continue; } if (g_utf8_validate(buf, -1, NULL)) { - poppler_page_find_text(page, buf); + matches = poppler_page_find_text(page, buf); + if (matches) { + g_list_free(matches); + } } g_object_unref(page); } From c629b189898694e3bd27039d834ec4423fbf18e8 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sat, 15 Jun 2024 14:04:48 +0930 Subject: [PATCH 20/27] Reorder utf16ToUtf8() args so each length argument follows the string --- poppler/UTF.cc | 12 ++---------- poppler/UTF.h | 15 ++++++++------- qt5/tests/check_utf_conversion.cpp | 2 +- qt6/tests/check_utf_conversion.cpp | 2 +- 4 files changed, 12 insertions(+), 19 deletions(-) diff --git a/poppler/UTF.cc b/poppler/UTF.cc index 2269a3761..d74236c5b 100644 --- a/poppler/UTF.cc +++ b/poppler/UTF.cc @@ -438,15 +438,7 @@ int utf16CountUtf8Bytes(const uint16_t *utf16) return count; } -// Convert UTF-16 to UTF-8 -// utf16- UTF-16 string to convert. If not null terminated, set maxUtf16 to num -// code units to convert -// utf8 - output buffer to write UTF-8 to. Output will always be null terminated. -// maxUtf8 - maximum size of output buffer including space for null. -// maxUtf16 - maximum number of UTF-16 code units to convert. Conversion stops when -// either this count is reached or a null is encountered. -// Returns number of UTF-8 bytes written (excluding NULL). -int utf16ToUtf8(const uint16_t *utf16, char *utf8, int maxUtf8, int maxUtf16) +int utf16ToUtf8(const uint16_t *utf16, int maxUtf16, char *utf8, int maxUtf8) { uint32_t codepoint = 0; uint32_t state = 0; @@ -492,7 +484,7 @@ char *utf16ToUtf8(const uint16_t *utf16, int *len) *len = n; } char *utf8 = (char *)gmalloc(n + 1); - utf16ToUtf8(utf16, utf8, n + 1, INT_MAX); + utf16ToUtf8(utf16, INT_MAX, utf8, n + 1); return utf8; } diff --git a/poppler/UTF.h b/poppler/UTF.h index eaa656be6..d1cf625b2 100644 --- a/poppler/UTF.h +++ b/poppler/UTF.h @@ -124,14 +124,15 @@ std::string POPPLER_PRIVATE_EXPORT utf8ToUtf16WithBom(const std::string &utf8); int POPPLER_PRIVATE_EXPORT utf16CountUtf8Bytes(const uint16_t *utf16); // Convert UTF-16 to UTF-8 -// utf16- UTF-16 string to convert. If not null terminated, set maxUtf16 to num -// code units to convert -// utf8 - output buffer to write UTF-8 to. Output will always be null terminated. -// maxUtf8 - maximum size of output buffer including space for null. -// maxUtf16 - maximum number of UTF-16 code units to convert. Conversion stops when -// either this count is reached or a null is encountered. +// utf16 - UTF-16 string to convert. If not null terminated, ensure +// maxUtf16 is set the the exact number of code units to convert. +// maxUtf16 - Maximum number of UTF-16 code units to convert. Conversion stops +// when either this count is reached or a null is encountered. +// utf8 - Output buffer to write the UTF-8 string to. Output will always be +// null terminated. +// maxUtf8 - Maximum size of the output buffer including space for null. // Returns number of UTF-8 bytes written (excluding NULL). -int POPPLER_PRIVATE_EXPORT utf16ToUtf8(const uint16_t *utf16, char *utf8, int maxUtf8, int maxUtf16); +int POPPLER_PRIVATE_EXPORT utf16ToUtf8(const uint16_t *utf16, int maxUtf16, char *utf8, int maxUtf8); // Allocate utf8 string and convert utf16 into it. char POPPLER_PRIVATE_EXPORT *utf16ToUtf8(const uint16_t *utf16, int *len = nullptr); diff --git a/qt5/tests/check_utf_conversion.cpp b/qt5/tests/check_utf_conversion.cpp index e3933e86f..46f0f83b9 100644 --- a/qt5/tests/check_utf_conversion.cpp +++ b/qt5/tests/check_utf_conversion.cpp @@ -113,7 +113,7 @@ void TestUTFConversion::testUTF() QCOMPARE(len, (int)strlen(str)); Q_ASSERT(len < (int)sizeof(utf8Buf)); // if this fails, make utf8Buf larger - len = utf16ToUtf8(s.utf16(), utf8Buf, sizeof(utf8Buf), INT_MAX); + len = utf16ToUtf8(s.utf16(), INT_MAX, utf8Buf, sizeof(utf8Buf)); QVERIFY(compare(utf8Buf, str)); QCOMPARE(len, (int)strlen(str)); diff --git a/qt6/tests/check_utf_conversion.cpp b/qt6/tests/check_utf_conversion.cpp index 943c55398..3b7f7a04a 100644 --- a/qt6/tests/check_utf_conversion.cpp +++ b/qt6/tests/check_utf_conversion.cpp @@ -111,7 +111,7 @@ void TestUTFConversion::testUTF() QCOMPARE(len, (int)strlen(str)); Q_ASSERT(len < (int)sizeof(utf8Buf)); // if this fails, make utf8Buf larger - len = utf16ToUtf8(s.utf16(), utf8Buf, sizeof(utf8Buf), INT_MAX); + len = utf16ToUtf8(s.utf16(), INT_MAX, utf8Buf, sizeof(utf8Buf)); QVERIFY(compare(utf8Buf, str)); QCOMPARE(len, (int)strlen(str)); From 3a9a34a4bee771c547ceaeeab2cd639d825fa5b5 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sat, 15 Jun 2024 19:22:25 +0930 Subject: [PATCH 21/27] Reorder utf8ToUtf16() args so each length argument follows the string --- poppler/UTF.cc | 12 ++---------- poppler/UTF.h | 14 +++++++------- qt5/tests/check_utf_conversion.cpp | 2 +- qt6/tests/check_utf_conversion.cpp | 2 +- utils/Win32Console.cc | 2 +- 5 files changed, 12 insertions(+), 20 deletions(-) diff --git a/poppler/UTF.cc b/poppler/UTF.cc index d74236c5b..a580b441c 100644 --- a/poppler/UTF.cc +++ b/poppler/UTF.cc @@ -289,15 +289,7 @@ int utf8CountUtf16CodeUnits(const char *utf8) return count; } -// Convert UTF-8 to UTF-16 -// utf8- UTF-8 string to convert. If not null terminated, set maxUtf8 to num -// bytes to convert -// utf16 - output buffer to write UTF-16 to. Output will always be null terminated. -// maxUtf16 - maximum size of output buffer including space for null. -// maxUtf8 - maximum number of UTF-8 bytes to convert. Conversion stops when -// either this count is reached or a null is encountered. -// Returns number of UTF-16 code units written (excluding NULL). -int utf8ToUtf16(const char *utf8, uint16_t *utf16, int maxUtf16, int maxUtf8) +int utf8ToUtf16(const char *utf8, int maxUtf8, uint16_t *utf16, int maxUtf16) { uint16_t *p = utf16; uint32_t codepoint; @@ -349,7 +341,7 @@ uint16_t *utf8ToUtf16(const char *utf8, int *len) *len = n; } uint16_t *utf16 = (uint16_t *)gmallocn(n + 1, sizeof(uint16_t)); - utf8ToUtf16(utf8, utf16, n + 1, INT_MAX); + utf8ToUtf16(utf8, INT_MAX, utf16, n + 1); return utf16; } diff --git a/poppler/UTF.h b/poppler/UTF.h index d1cf625b2..7e53568dd 100644 --- a/poppler/UTF.h +++ b/poppler/UTF.h @@ -90,14 +90,14 @@ int POPPLER_PRIVATE_EXPORT utf8ToUCS4(const char *utf8, Unicode **ucs4_out); int POPPLER_PRIVATE_EXPORT utf8CountUtf16CodeUnits(const char *utf8); // Convert UTF-8 to UTF-16 -// utf8- UTF-8 string to convert. If not null terminated, set maxUtf8 to num -// bytes to convert -// utf16 - output buffer to write UTF-16 to. Output will always be null terminated. -// maxUtf16 - maximum size of output buffer including space for null. -// maxUtf8 - maximum number of UTF-8 bytes to convert. Conversion stops when -// either this count is reached or a null is encountered. +// utf8 - UTF-8 string to convert. If not null terminated, ensure +// maxUtf8 is set the the exact number of bytes to convert. +// maxUtf8 - Maximum number of UTF-8 bytes to convert. Conversion stops when +// either this count is reached or a null is encountered. +// utf16 - Output buffer to write UTF-16 to. Output will always be null terminated. +// maxUtf16 - Maximum size of output buffer including space for null. // Returns number of UTF-16 code units written (excluding NULL). -int POPPLER_PRIVATE_EXPORT utf8ToUtf16(const char *utf8, uint16_t *utf16, int maxUtf16, int maxUtf8); +int POPPLER_PRIVATE_EXPORT utf8ToUtf16(const char *utf8, int maxUtf8, uint16_t *utf16, int maxUtf16); // Allocate utf16 string and convert utf8 into it. uint16_t POPPLER_PRIVATE_EXPORT *utf8ToUtf16(const char *utf8, int *len = nullptr); diff --git a/qt5/tests/check_utf_conversion.cpp b/qt5/tests/check_utf_conversion.cpp index 46f0f83b9..6a4280b87 100644 --- a/qt5/tests/check_utf_conversion.cpp +++ b/qt5/tests/check_utf_conversion.cpp @@ -94,7 +94,7 @@ void TestUTFConversion::testUTF() QCOMPARE(len, s.size()); // QString size() returns number of code units, not code points Q_ASSERT(len < (int)sizeof(utf16Buf)); // if this fails, make utf16Buf larger - len = utf8ToUtf16(str, utf16Buf, sizeof(utf16Buf), INT_MAX); + len = utf8ToUtf16(str, INT_MAX, utf16Buf, sizeof(utf16Buf)); QVERIFY(compare(utf16Buf, s.utf16())); QCOMPARE(len, s.size()); diff --git a/qt6/tests/check_utf_conversion.cpp b/qt6/tests/check_utf_conversion.cpp index 3b7f7a04a..7a7e5b5c7 100644 --- a/qt6/tests/check_utf_conversion.cpp +++ b/qt6/tests/check_utf_conversion.cpp @@ -92,7 +92,7 @@ void TestUTFConversion::testUTF() QCOMPARE(len, s.size()); // QString size() returns number of code units, not code points Q_ASSERT(len < (int)sizeof(utf16Buf)); // if this fails, make utf16Buf larger - len = utf8ToUtf16(str, utf16Buf, sizeof(utf16Buf), INT_MAX); + len = utf8ToUtf16(str, INT_MAX, utf16Buf, sizeof(utf16Buf)); QVERIFY(compare(utf16Buf, s.utf16())); QCOMPARE(len, s.size()); diff --git a/utils/Win32Console.cc b/utils/Win32Console.cc index ea46e17b6..27ff4dc0b 100644 --- a/utils/Win32Console.cc +++ b/utils/Win32Console.cc @@ -49,7 +49,7 @@ static void flush(bool all = false) } if (nchars > 0) { - DWORD wlen = utf8ToUtf16(buf, (uint16_t *)wbuf, BUF_SIZE, nchars); + DWORD wlen = utf8ToUtf16(buf, nchars, (uint16_t *)wbuf, BUF_SIZE); WriteConsoleW(consoleHandle, wbuf, wlen, &wlen, nullptr); if (nchars < bufLen) { memmove(buf, buf + nchars, bufLen - nchars); From 935734b8a272ad8f1acdd9df057b8e3616c181c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nelson=20Ben=C3=ADtez=20Le=C3=B3n?= Date: Thu, 20 Jun 2024 09:00:47 +0000 Subject: [PATCH 22/27] glib find text fuzzer: correctly free the matches list --- glib/tests/fuzzing/find_text_fuzzer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glib/tests/fuzzing/find_text_fuzzer.cc b/glib/tests/fuzzing/find_text_fuzzer.cc index 1db5d7a76..4bab80f3e 100644 --- a/glib/tests/fuzzing/find_text_fuzzer.cc +++ b/glib/tests/fuzzing/find_text_fuzzer.cc @@ -36,7 +36,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) if (g_utf8_validate(buf, -1, NULL)) { matches = poppler_page_find_text(page, buf); if (matches) { - g_list_free(matches); + g_list_free_full(matches, (GDestroyNotify)poppler_rectangle_free); } } g_object_unref(page); From cd59895eb14d98776a416a9aa8d7a3cdc788b278 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Fri, 21 Jun 2024 00:43:40 +0200 Subject: [PATCH 23/27] Update (C) --- poppler/UTF.cc | 2 +- poppler/UTF.h | 2 +- utils/Win32Console.cc | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/poppler/UTF.cc b/poppler/UTF.cc index a580b441c..6f67dccfd 100644 --- a/poppler/UTF.cc +++ b/poppler/UTF.cc @@ -14,7 +14,7 @@ // under GPL version 2 or later // // Copyright (C) 2008 Koji Otani -// Copyright (C) 2012, 2017, 2021, 2023 Adrian Johnson +// Copyright (C) 2012, 2017, 2021, 2023, 2024 Adrian Johnson // Copyright (C) 2012 Hib Eris // Copyright (C) 2016, 2018-2022, 2024 Albert Astals Cid // Copyright (C) 2016 Jason Crain diff --git a/poppler/UTF.h b/poppler/UTF.h index 7e53568dd..bd57188df 100644 --- a/poppler/UTF.h +++ b/poppler/UTF.h @@ -4,7 +4,7 @@ // // This file is licensed under the GPLv2 or later // -// Copyright (C) 2012, 2017, 2021, 2023 Adrian Johnson +// Copyright (C) 2012, 2017, 2021, 2023, 2024 Adrian Johnson // Copyright (C) 2016 Jason Crain // Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, . Work sponsored by the LiMux project of the city of Munich // Copyright (C) 2018 Nelson Benítez León diff --git a/utils/Win32Console.cc b/utils/Win32Console.cc index 27ff4dc0b..deac2458a 100644 --- a/utils/Win32Console.cc +++ b/utils/Win32Console.cc @@ -4,7 +4,7 @@ // // This file is licensed under the GPLv2 or later // -// Copyright (C) 2017 Adrian Johnson +// Copyright (C) 2017, 2024 Adrian Johnson // // To see a description of the changes please see the Changelog file that // came with your tarball or type make ChangeLog if you are building from git From fe0513a2bd4fe7a0ba9c3caf73573098392d2267 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Wed, 26 Jun 2024 00:20:16 +0200 Subject: [PATCH 24/27] Fix crash in FoFiType1::parse When the content to parse ends in "/FontName " --- fofi/FoFiType1.cc | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/fofi/FoFiType1.cc b/fofi/FoFiType1.cc index eaa741437..5a3386b8c 100644 --- a/fofi/FoFiType1.cc +++ b/fofi/FoFiType1.cc @@ -197,9 +197,15 @@ class FoFiType1Tokenizer pos = stringView.find_first_of(tokenSeparators, currentPos); } if (pos == std::string_view::npos) { - std::string_view token = stringView.substr(currentPos, length - currentPos); - currentPos = length; - return token; + const auto tokenLength = length - currentPos; + if (tokenLength > 0) { + std::string_view token = stringView.substr(currentPos, tokenLength); + currentPos = length; + return token; + } else { + currentPos = length; + return {}; + } } std::string_view token = stringView.substr(currentPos, pos - currentPos); From 5e4d80275ee7800ec266f58d5178b34654b5bf12 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Thu, 27 Jun 2024 19:32:18 +0200 Subject: [PATCH 25/27] Update (C) --- fofi/FoFiType1.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fofi/FoFiType1.cc b/fofi/FoFiType1.cc index 5a3386b8c..770f05b4c 100644 --- a/fofi/FoFiType1.cc +++ b/fofi/FoFiType1.cc @@ -13,7 +13,7 @@ // All changes made under the Poppler project to this file are licensed // under GPL version 2 or later // -// Copyright (C) 2005, 2008, 2010, 2018, 2021-2023 Albert Astals Cid +// Copyright (C) 2005, 2008, 2010, 2018, 2021-2024 Albert Astals Cid // Copyright (C) 2005 Kristian Høgsberg // Copyright (C) 2010 Jakub Wilk // Copyright (C) 2014 Carlos Garcia Campos From 81b83e83c053420d452a31d0cc6321965cb5e358 Mon Sep 17 00:00:00 2001 From: Pratham Gandhi Date: Mon, 1 Jul 2024 19:19:21 +0000 Subject: [PATCH 26/27] Qt: Implement reset forms link --- qt5/src/poppler-annotation.cc | 4 ++++ qt5/src/poppler-document.cc | 19 +++++++++++++++++++ qt5/src/poppler-link-private.h | 10 ++++++++++ qt5/src/poppler-link.cc | 12 ++++++++++++ qt5/src/poppler-link.h | 28 ++++++++++++++++++++++++++++ qt5/src/poppler-page.cc | 13 ++++++++++--- qt5/src/poppler-qt5.h | 7 +++++++ qt6/src/poppler-document.cc | 19 +++++++++++++++++++ qt6/src/poppler-link-private.h | 10 ++++++++++ qt6/src/poppler-link.cc | 12 ++++++++++++ qt6/src/poppler-link.h | 28 ++++++++++++++++++++++++++++ qt6/src/poppler-page.cc | 13 ++++++++++--- qt6/src/poppler-qt6.h | 7 +++++++ 13 files changed, 176 insertions(+), 6 deletions(-) diff --git a/qt5/src/poppler-annotation.cc b/qt5/src/poppler-annotation.cc index e15523cfa..a5551c114 100644 --- a/qt5/src/poppler-annotation.cc +++ b/qt5/src/poppler-annotation.cc @@ -4083,6 +4083,10 @@ void LinkAnnotation::store(QDomNode &node, QDomDocument &document) const hyperlinkElement.setAttribute(QStringLiteral("type"), QStringLiteral("Hide")); break; } + case Poppler::Link::ResetForm: { + hyperlinkElement.setAttribute(QStringLiteral("type"), QStringLiteral("ResetForm")); + break; + } case Poppler::Link::None: break; } diff --git a/qt5/src/poppler-document.cc b/qt5/src/poppler-document.cc index bae6b728c..66e58cdb5 100644 --- a/qt5/src/poppler-document.cc +++ b/qt5/src/poppler-document.cc @@ -56,6 +56,7 @@ #include "poppler-form.h" #include "poppler-private.h" +#include "poppler-link-private.h" #include "poppler-page-private.h" #include "poppler-outline-private.h" @@ -801,6 +802,24 @@ Link *Document::additionalAction(DocumentAdditionalActionsType type) const return action; } +void Document::applyResetFormsLink(const LinkResetForm &link) +{ + const LinkResetFormPrivate *lrfp = link.d_func(); + Catalog *catalog = m_doc->doc->getCatalog(); + if (catalog && catalog->isOk()) { + Form *form = catalog->getForm(); + if (form) { + std::vector stdStringFields; + const QStringList fields = lrfp->m_fields; + stdStringFields.reserve(fields.size()); + for (const auto &field : fields) { + stdStringFields.emplace_back(field.toStdString()); + } + form->reset(stdStringFields, lrfp->m_exclude); + } + } +} + QStringList Document::scripts() const { Catalog *catalog = m_doc->doc->getCatalog(); diff --git a/qt5/src/poppler-link-private.h b/qt5/src/poppler-link-private.h index 7e6f6b071..6d00b2c85 100644 --- a/qt5/src/poppler-link-private.h +++ b/qt5/src/poppler-link-private.h @@ -67,6 +67,16 @@ class LinkHidePrivate : public LinkPrivate bool isShow; }; +class LinkResetFormPrivate : public LinkPrivate +{ +public: + LinkResetFormPrivate(const QRectF &area, const QStringList &fields, const bool exclude) : LinkPrivate(area), m_fields(fields), m_exclude(exclude) { } + ~LinkResetFormPrivate() override; + + QStringList m_fields; + bool m_exclude; +}; + } #endif diff --git a/qt5/src/poppler-link.cc b/qt5/src/poppler-link.cc index eb841ca55..d363398d6 100644 --- a/qt5/src/poppler-link.cc +++ b/qt5/src/poppler-link.cc @@ -78,6 +78,8 @@ LinkOCGStatePrivate::~LinkOCGStatePrivate() = default; LinkHidePrivate::~LinkHidePrivate() = default; +LinkResetFormPrivate::~LinkResetFormPrivate() = default; + class LinkGotoPrivate : public LinkPrivate { public: @@ -694,4 +696,14 @@ bool LinkHide::isShowAction() const Q_D(const LinkHide); return d->isShow; } + +// LinkResetForm +LinkResetForm::LinkResetForm(LinkResetFormPrivate *lrfp) : Link(*lrfp) { } + +LinkResetForm::~LinkResetForm() { } + +Link::LinkType LinkResetForm::linkType() const +{ + return ResetForm; +} } diff --git a/qt5/src/poppler-link.h b/qt5/src/poppler-link.h index b37e32511..8ccb38c8f 100644 --- a/qt5/src/poppler-link.h +++ b/qt5/src/poppler-link.h @@ -53,6 +53,7 @@ class LinkDestinationPrivate; class LinkRenditionPrivate; class LinkOCGStatePrivate; class LinkHidePrivate; +class LinkResetFormPrivate; class MediaRendition; class MovieAnnotation; class ScreenAnnotation; @@ -203,6 +204,7 @@ class POPPLER_QT5_EXPORT Link JavaScript, ///< A JavaScript code to be interpreted \since 0.10 OCGState, ///< An Optional Content Group state change \since 0.50 Hide, ///< An action to hide a field \since 0.64 + ResetForm, ///< An action to reset the form \since 24.07 }; /** @@ -694,6 +696,32 @@ class POPPLER_QT5_EXPORT LinkHide : public Link Q_DISABLE_COPY(LinkHide) }; +/** + * ResetForm: an action to reset form fields. + * + * \since 24.07 + */ +class POPPLER_QT5_EXPORT LinkResetForm : public Link +{ + friend class Document; + +public: + /** + * Creates a new ResetForm link. This is only used by Poppler::Page + */ + explicit LinkResetForm(LinkResetFormPrivate *lrfp); + /* + * Destructor + */ + ~LinkResetForm() override; + + LinkType linkType() const override; + +private: + Q_DECLARE_PRIVATE(LinkResetForm) + Q_DISABLE_COPY(LinkResetForm) +}; + } #endif diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc index 05de82da1..7036f4645 100644 --- a/qt5/src/poppler-page.cc +++ b/qt5/src/poppler-page.cc @@ -335,9 +335,16 @@ Link *PageData::convertLinkActionToLink(::LinkAction *a, DocumentData *parentDoc popplerLink = new LinkHide(lhp); } break; - case actionResetForm: - // Not handled in Qt5 front-end yet - break; + case actionResetForm: { + ::LinkResetForm *lrf = (::LinkResetForm *)a; + std::vector stdStringFields = lrf->getFields(); + QStringList qStringFields; + for (const std::string &str : stdStringFields) { + qStringFields << QString::fromStdString(str); + } + LinkResetFormPrivate *lrfp = new LinkResetFormPrivate(linkArea, qStringFields, lrf->getExclude()); + popplerLink = new LinkResetForm(lrfp); + } break; case actionUnknown: break; diff --git a/qt5/src/poppler-qt5.h b/qt5/src/poppler-qt5.h index f1cdb7c0c..a43752449 100644 --- a/qt5/src/poppler-qt5.h +++ b/qt5/src/poppler-qt5.h @@ -1869,6 +1869,13 @@ QString subject = m_doc->info("Subject"); */ OptContentModel *optionalContentModel(); + /** + Resets the form with the details contained in the \p link. + + \since 24.07 + */ + void applyResetFormsLink(const LinkResetForm &link); + /** Document-level JavaScript scripts. diff --git a/qt6/src/poppler-document.cc b/qt6/src/poppler-document.cc index ef35cbbde..1809042c0 100644 --- a/qt6/src/poppler-document.cc +++ b/qt6/src/poppler-document.cc @@ -56,6 +56,7 @@ #include "poppler-form.h" #include "poppler-private.h" +#include "poppler-link-private.h" #include "poppler-page-private.h" #include "poppler-outline-private.h" @@ -741,6 +742,24 @@ OptContentModel *Document::optionalContentModel() return (OptContentModel *)m_doc->m_optContentModel; } +void Document::applyResetFormsLink(const LinkResetForm &link) +{ + const LinkResetFormPrivate *lrfp = link.d_func(); + Catalog *catalog = m_doc->doc->getCatalog(); + if (catalog && catalog->isOk()) { + Form *form = catalog->getForm(); + if (form) { + std::vector stdStringFields; + const QStringList fields = lrfp->m_fields; + stdStringFields.reserve(fields.size()); + for (const auto &field : fields) { + stdStringFields.emplace_back(field.toStdString()); + } + form->reset(stdStringFields, lrfp->m_exclude); + } + } +} + QStringList Document::scripts() const { Catalog *catalog = m_doc->doc->getCatalog(); diff --git a/qt6/src/poppler-link-private.h b/qt6/src/poppler-link-private.h index edf334b3e..baaefb179 100644 --- a/qt6/src/poppler-link-private.h +++ b/qt6/src/poppler-link-private.h @@ -67,6 +67,16 @@ class LinkHidePrivate : public LinkPrivate bool isShow; }; +class LinkResetFormPrivate : public LinkPrivate +{ +public: + LinkResetFormPrivate(const QRectF &area, const QStringList &fields, const bool exclude) : LinkPrivate(area), m_fields(fields), m_exclude(exclude) { } + ~LinkResetFormPrivate() override; + + QStringList m_fields; + bool m_exclude; +}; + } #endif diff --git a/qt6/src/poppler-link.cc b/qt6/src/poppler-link.cc index e85e18255..baad70cbc 100644 --- a/qt6/src/poppler-link.cc +++ b/qt6/src/poppler-link.cc @@ -75,6 +75,8 @@ LinkOCGStatePrivate::~LinkOCGStatePrivate() = default; LinkHidePrivate::~LinkHidePrivate() = default; +LinkResetFormPrivate::~LinkResetFormPrivate() = default; + class LinkGotoPrivate : public LinkPrivate { public: @@ -697,4 +699,14 @@ bool LinkHide::isShowAction() const Q_D(const LinkHide); return d->isShow; } + +// LinkResetForm +LinkResetForm::LinkResetForm(LinkResetFormPrivate *lrfp) : Link(*lrfp) { } + +LinkResetForm::~LinkResetForm() { } + +Link::LinkType LinkResetForm::linkType() const +{ + return ResetForm; +} } diff --git a/qt6/src/poppler-link.h b/qt6/src/poppler-link.h index 9e117fd98..67cdc20c0 100644 --- a/qt6/src/poppler-link.h +++ b/qt6/src/poppler-link.h @@ -53,6 +53,7 @@ class LinkDestinationPrivate; class LinkRenditionPrivate; class LinkOCGStatePrivate; class LinkHidePrivate; +class LinkResetFormPrivate; class MediaRendition; class MovieAnnotation; class ScreenAnnotation; @@ -201,6 +202,7 @@ class POPPLER_QT6_EXPORT Link JavaScript, ///< A JavaScript code to be interpreted OCGState, ///< An Optional Content Group state change Hide, ///< An action to hide a field + ResetForm, ///< An action to reset the form \since 24.07 }; /** @@ -668,6 +670,32 @@ class POPPLER_QT6_EXPORT LinkHide : public Link Q_DISABLE_COPY(LinkHide) }; +/** + * ResetForm: an action to reset form fields. + * + * \since 24.07 + */ +class POPPLER_QT6_EXPORT LinkResetForm : public Link +{ + friend class Document; + +public: + /** + * Creates a new ResetForm link. This is only used by Poppler::Page + */ + explicit LinkResetForm(LinkResetFormPrivate *lrfp); + /* + * Destructor + */ + ~LinkResetForm() override; + + LinkType linkType() const override; + +private: + Q_DECLARE_PRIVATE(LinkResetForm) + Q_DISABLE_COPY(LinkResetForm) +}; + } #endif diff --git a/qt6/src/poppler-page.cc b/qt6/src/poppler-page.cc index 6a8446321..d7e49a52d 100644 --- a/qt6/src/poppler-page.cc +++ b/qt6/src/poppler-page.cc @@ -334,9 +334,16 @@ std::unique_ptr PageData::convertLinkActionToLink(::LinkAction *a, Documen popplerLink = std::make_unique(lhp); } break; - case actionResetForm: - // Not handled in Qt6 front-end yet - break; + case actionResetForm: { + ::LinkResetForm *lrf = (::LinkResetForm *)a; + std::vector stdStringFields = lrf->getFields(); + QStringList qStringFields; + for (const std::string &str : stdStringFields) { + qStringFields << QString::fromStdString(str); + } + LinkResetFormPrivate *lrfp = new LinkResetFormPrivate(linkArea, qStringFields, lrf->getExclude()); + popplerLink = std::make_unique(lrfp); + } break; case actionUnknown: break; diff --git a/qt6/src/poppler-qt6.h b/qt6/src/poppler-qt6.h index 995a32afa..68dd4c56f 100644 --- a/qt6/src/poppler-qt6.h +++ b/qt6/src/poppler-qt6.h @@ -1672,6 +1672,13 @@ QString subject = m_doc->info("Subject"); */ OptContentModel *optionalContentModel(); + /** + Resets the form with the details contained in the \p link. + + \since 24.07 + */ + void applyResetFormsLink(const LinkResetForm &link); + /** Document-level JavaScript scripts. From a16aa8bc839e5dd4a2c8d75aff010416477b392b Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Mon, 1 Jul 2024 21:22:52 +0200 Subject: [PATCH 27/27] Update (C) --- qt5/src/poppler-annotation.cc | 1 + qt5/src/poppler-document.cc | 1 + qt5/src/poppler-link-private.h | 1 + qt5/src/poppler-link.cc | 1 + qt5/src/poppler-link.h | 1 + qt5/src/poppler-page.cc | 1 + qt5/src/poppler-qt5.h | 1 + qt6/src/poppler-document.cc | 1 + qt6/src/poppler-link-private.h | 1 + qt6/src/poppler-link.cc | 1 + qt6/src/poppler-link.h | 1 + qt6/src/poppler-page.cc | 1 + qt6/src/poppler-qt6.h | 1 + 13 files changed, 13 insertions(+) diff --git a/qt5/src/poppler-annotation.cc b/qt5/src/poppler-annotation.cc index a5551c114..42a203290 100644 --- a/qt5/src/poppler-annotation.cc +++ b/qt5/src/poppler-annotation.cc @@ -15,6 +15,7 @@ * Copyright (C) 2020 Thorsten Behrens * Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, . Work sponsored by Technische Universität Dresden * Copyright (C) 2021 Mahmoud Ahmed Khalil + * Copyright (C) 2024 Pratham Gandhi * Adapting code from * Copyright (C) 2004 by Enrico Ros * diff --git a/qt5/src/poppler-document.cc b/qt5/src/poppler-document.cc index 66e58cdb5..ffa93fde7 100644 --- a/qt5/src/poppler-document.cc +++ b/qt5/src/poppler-document.cc @@ -20,6 +20,7 @@ * Copyright (C) 2020 Thorsten Behrens * Copyright (C) 2021 Mahmoud Khalil * Copyright (C) 2021 Hubert Figuiere + * Copyright (C) 2024 Pratham Gandhi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/qt5/src/poppler-link-private.h b/qt5/src/poppler-link-private.h index 6d00b2c85..fb115c2fe 100644 --- a/qt5/src/poppler-link-private.h +++ b/qt5/src/poppler-link-private.h @@ -2,6 +2,7 @@ * Copyright (C) 2016, 2018, 2020, 2021 Albert Astals Cid * Copyright (C) 2018 Intevation GmbH * Copyright (C) 2020 Oliver Sander + * Copyright (C) 2024 Pratham Gandhi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/qt5/src/poppler-link.cc b/qt5/src/poppler-link.cc index d363398d6..8dceb283b 100644 --- a/qt5/src/poppler-link.cc +++ b/qt5/src/poppler-link.cc @@ -7,6 +7,7 @@ * Copyright (C) 2018 Intevation GmbH * Copyright (C) 2018 Adam Reichold * Copyright (C) 2020 Oliver Sander + * Copyright (C) 2024 Pratham Gandhi * Adapting code from * Copyright (C) 2004 by Enrico Ros * diff --git a/qt5/src/poppler-link.h b/qt5/src/poppler-link.h index 8ccb38c8f..6c93bec85 100644 --- a/qt5/src/poppler-link.h +++ b/qt5/src/poppler-link.h @@ -6,6 +6,7 @@ * Copyright (C) 2013, Anthony Granger * Copyright (C) 2018 Intevation GmbH * Copyright (C) 2020 Oliver Sander + * Copyright (C) 2024 Pratham Gandhi * Adapting code from * Copyright (C) 2004 by Enrico Ros * diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc index 7036f4645..cd3c1c51e 100644 --- a/qt5/src/poppler-page.cc +++ b/qt5/src/poppler-page.cc @@ -29,6 +29,7 @@ * Copyright (C) 2021 Thomas Huxhorn * Copyright (C) 2023 Kevin Ottens . Work sponsored by De Bortoli Wines * Copyright (C) 2024 Stefan Brüns + * Copyright (C) 2024 Pratham Gandhi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/qt5/src/poppler-qt5.h b/qt5/src/poppler-qt5.h index a43752449..de8adad95 100644 --- a/qt5/src/poppler-qt5.h +++ b/qt5/src/poppler-qt5.h @@ -30,6 +30,7 @@ * Copyright (C) 2021 Georgiy Sgibnev . Work sponsored by lab50.net. * Copyright (C) 2022 Martin * Copyright (C) 2023 Kevin Ottens . Work sponsored by De Bortoli Wines + * Copyright (C) 2024 Pratham Gandhi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/qt6/src/poppler-document.cc b/qt6/src/poppler-document.cc index 1809042c0..4af82baef 100644 --- a/qt6/src/poppler-document.cc +++ b/qt6/src/poppler-document.cc @@ -20,6 +20,7 @@ * Copyright (C) 2020 Thorsten Behrens * Copyright (C) 2021 Mahmoud Khalil * Copyright (C) 2021 Hubert Figuiere + * Copyright (C) 2024 Pratham Gandhi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/qt6/src/poppler-link-private.h b/qt6/src/poppler-link-private.h index baaefb179..ac6dd3a09 100644 --- a/qt6/src/poppler-link-private.h +++ b/qt6/src/poppler-link-private.h @@ -2,6 +2,7 @@ * Copyright (C) 2016, 2018, 2020, 2021 Albert Astals Cid * Copyright (C) 2018 Intevation GmbH * Copyright (C) 2020, 2021 Oliver Sander + * Copyright (C) 2024 Pratham Gandhi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/qt6/src/poppler-link.cc b/qt6/src/poppler-link.cc index baad70cbc..e3934a9ae 100644 --- a/qt6/src/poppler-link.cc +++ b/qt6/src/poppler-link.cc @@ -7,6 +7,7 @@ * Copyright (C) 2018 Intevation GmbH * Copyright (C) 2018 Adam Reichold * Copyright (C) 2020, 2021 Oliver Sander + * Copyright (C) 2024 Pratham Gandhi * Adapting code from * Copyright (C) 2004 by Enrico Ros * diff --git a/qt6/src/poppler-link.h b/qt6/src/poppler-link.h index 67cdc20c0..784b1f97e 100644 --- a/qt6/src/poppler-link.h +++ b/qt6/src/poppler-link.h @@ -6,6 +6,7 @@ * Copyright (C) 2013, Anthony Granger * Copyright (C) 2018 Intevation GmbH * Copyright (C) 2020, 2021 Oliver Sander + * Copyright (C) 2024 Pratham Gandhi * Adapting code from * Copyright (C) 2004 by Enrico Ros * diff --git a/qt6/src/poppler-page.cc b/qt6/src/poppler-page.cc index d7e49a52d..d586ef64c 100644 --- a/qt6/src/poppler-page.cc +++ b/qt6/src/poppler-page.cc @@ -28,6 +28,7 @@ * Copyright (C) 2021 Thomas Huxhorn * Copyright (C) 2023 Kevin Ottens . Work sponsored by De Bortoli Wines * Copyright (C) 2024 Stefan Brüns + * Copyright (C) 2024 Pratham Gandhi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/qt6/src/poppler-qt6.h b/qt6/src/poppler-qt6.h index 68dd4c56f..eda10da41 100644 --- a/qt6/src/poppler-qt6.h +++ b/qt6/src/poppler-qt6.h @@ -30,6 +30,7 @@ * Copyright (C) 2021 Georgiy Sgibnev . Work sponsored by lab50.net. * Copyright (C) 2022 Martin * Copyright (C) 2023 Kevin Ottens . Work sponsored by De Bortoli Wines + * Copyright (C) 2024 Pratham Gandhi * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by