From 3503c03ece2fd912f4ba4767894eb97d8f9aae07 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Thu, 15 Oct 2020 21:03:59 +0200 Subject: pdfium: add an FPDFBitmap_Create() wrapper Fixes a leak in PDFiumPage::getChecksum(). Change-Id: I57471a26702f1d3dd69e9e18a4067ce0e724e358 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104386 Tested-by: Jenkins Reviewed-by: Miklos Vajna --- include/vcl/filter/PDFiumLibrary.hxx | 2 ++ vcl/source/filter/ipdf/pdfread.cxx | 31 +++++++++++++++---------------- vcl/source/pdf/PDFiumLibrary.cxx | 26 ++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/include/vcl/filter/PDFiumLibrary.hxx b/include/vcl/filter/PDFiumLibrary.hxx index f6687cceacb1..ee8a453a8b15 100644 --- a/include/vcl/filter/PDFiumLibrary.hxx +++ b/include/vcl/filter/PDFiumLibrary.hxx @@ -38,6 +38,7 @@ constexpr char constDictionaryKeyPopup[] = "Popup"; constexpr char constDictionaryKeyModificationDate[] = "M"; constexpr char constDictionaryKeyInteriorColor[] = "IC"; +class PDFiumBitmap; class PDFiumDocument; class PDFiumPageObject; @@ -56,6 +57,7 @@ public: OUString getLastError() const { return maLastError; } std::unique_ptr openDocument(const void* pData, int nSize); + std::unique_ptr createBitmap(int nWidth, int nHeight, int nAlpha); }; class VCL_DLLPUBLIC PDFiumBitmap final diff --git a/vcl/source/filter/ipdf/pdfread.cxx b/vcl/source/filter/ipdf/pdfread.cxx index 5e113ff2aba8..605ea45f8c23 100644 --- a/vcl/source/filter/ipdf/pdfread.cxx +++ b/vcl/source/filter/ipdf/pdfread.cxx @@ -155,24 +155,24 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector& rBi auto pPdfium = vcl::pdf::PDFiumLibrary::get(); // Load the buffer using pdfium. - FPDF_DOCUMENT pPdfDocument = FPDF_LoadMemDocument(pBuffer, nSize, /*password=*/nullptr); + std::unique_ptr pPdfDocument = pPdfium->openDocument(pBuffer, nSize); if (!pPdfDocument) return 0; - const int nPageCount = FPDF_GetPageCount(pPdfDocument); + const int nPageCount = pPdfDocument->getPageCount(); if (nPages <= 0) nPages = nPageCount; const size_t nLastPage = std::min(nPageCount, nFirstPage + nPages) - 1; for (size_t nPageIndex = nFirstPage; nPageIndex <= nLastPage; ++nPageIndex) { // Render next page. - FPDF_PAGE pPdfPage = FPDF_LoadPage(pPdfDocument, nPageIndex); + std::unique_ptr pPdfPage = pPdfDocument->openPage(nPageIndex); if (!pPdfPage) break; // Calculate the bitmap size in points. - size_t nPageWidthPoints = FPDF_GetPageWidth(pPdfPage); - size_t nPageHeightPoints = FPDF_GetPageHeight(pPdfPage); + size_t nPageWidthPoints = pPdfPage->getWidth(); + size_t nPageHeightPoints = pPdfPage->getHeight(); if (pSizeHint && pSizeHint->getX() && pSizeHint->getY()) { // Have a size hint, prefer that over the logic size from the PDF. @@ -183,21 +183,24 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector& rBi // Returned unit is points, convert that to pixel. const size_t nPageWidth = pointToPixel(nPageWidthPoints, fResolutionDPI); const size_t nPageHeight = pointToPixel(nPageHeightPoints, fResolutionDPI); - FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nPageWidth, nPageHeight, /*alpha=*/1); + std::unique_ptr pPdfBitmap + = pPdfium->createBitmap(nPageWidth, nPageHeight, /*alpha=*/1); if (!pPdfBitmap) break; - const FPDF_DWORD nColor = FPDFPage_HasTransparency(pPdfPage) ? 0x00000000 : 0xFFFFFFFF; - FPDFBitmap_FillRect(pPdfBitmap, 0, 0, nPageWidth, nPageHeight, nColor); - FPDF_RenderPageBitmap(pPdfBitmap, pPdfPage, /*start_x=*/0, /*start_y=*/0, nPageWidth, - nPageHeight, /*rotate=*/0, /*flags=*/0); + const FPDF_DWORD nColor + = FPDFPage_HasTransparency(pPdfPage->getPointer()) ? 0x00000000 : 0xFFFFFFFF; + FPDFBitmap_FillRect(pPdfBitmap->getPointer(), 0, 0, nPageWidth, nPageHeight, nColor); + FPDF_RenderPageBitmap(pPdfBitmap->getPointer(), pPdfPage->getPointer(), /*start_x=*/0, + /*start_y=*/0, nPageWidth, nPageHeight, /*rotate=*/0, /*flags=*/0); // Save the buffer as a bitmap. Bitmap aBitmap(Size(nPageWidth, nPageHeight), 24); { BitmapScopedWriteAccess pWriteAccess(aBitmap); - const auto pPdfBuffer = static_cast(FPDFBitmap_GetBuffer(pPdfBitmap)); - const int nStride = FPDFBitmap_GetStride(pPdfBitmap); + const auto pPdfBuffer + = static_cast(FPDFBitmap_GetBuffer(pPdfBitmap->getPointer())); + const int nStride = FPDFBitmap_GetStride(pPdfBitmap->getPointer()); for (size_t nRow = 0; nRow < nPageHeight; ++nRow) { ConstScanline pPdfLine = pPdfBuffer + (nStride * nRow); @@ -207,12 +210,8 @@ size_t RenderPDFBitmaps(const void* pBuffer, int nSize, std::vector& rBi } rBitmaps.emplace_back(std::move(aBitmap)); - FPDFBitmap_Destroy(pPdfBitmap); - FPDF_ClosePage(pPdfPage); } - FPDF_CloseDocument(pPdfDocument); - return rBitmaps.size(); #else (void)pBuffer; diff --git a/vcl/source/pdf/PDFiumLibrary.cxx b/vcl/source/pdf/PDFiumLibrary.cxx index 64fdd6a7e0d4..32c33580d1df 100644 --- a/vcl/source/pdf/PDFiumLibrary.cxx +++ b/vcl/source/pdf/PDFiumLibrary.cxx @@ -139,6 +139,21 @@ std::unique_ptr PDFium::openDocument(const void* pData, int nSiz return pPDFiumDocument; } +std::unique_ptr PDFium::createBitmap(int nWidth, int nHeight, int nAlpha) +{ + std::unique_ptr pPDFiumBitmap; + FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nWidth, nHeight, nAlpha); + if (!pPdfBitmap) + { + maLastError = "Failed to create bitmap"; + } + else + { + pPDFiumBitmap = std::make_unique(pPdfBitmap); + } + return pPDFiumBitmap; +} + PDFiumDocument::PDFiumDocument(FPDF_DOCUMENT pPdfDocument) : mpPdfDocument(pPdfDocument) { @@ -377,7 +392,8 @@ BitmapChecksum PDFiumPage::getChecksum() { size_t nPageWidth = getWidth(); size_t nPageHeight = getHeight(); - FPDF_BITMAP pPdfBitmap = FPDFBitmap_Create(nPageWidth, nPageHeight, /*alpha=*/1); + auto pPdfBitmap + = std::make_unique(FPDFBitmap_Create(nPageWidth, nPageHeight, /*alpha=*/1)); if (!pPdfBitmap) { return 0; @@ -385,13 +401,15 @@ BitmapChecksum PDFiumPage::getChecksum() // Intentionally not using FPDF_ANNOT here, annotations/commenting is OK to not affect the // checksum, signature verification wants this. - FPDF_RenderPageBitmap(pPdfBitmap, mpPage, /*start_x=*/0, /*start_y=*/0, nPageWidth, nPageHeight, + FPDF_RenderPageBitmap(pPdfBitmap->getPointer(), mpPage, /*start_x=*/0, /*start_y=*/0, + nPageWidth, nPageHeight, /*rotate=*/0, /*flags=*/0); Bitmap aBitmap(Size(nPageWidth, nPageHeight), 24); { BitmapScopedWriteAccess pWriteAccess(aBitmap); - const auto pPdfBuffer = static_cast(FPDFBitmap_GetBuffer(pPdfBitmap)); - const int nStride = FPDFBitmap_GetStride(pPdfBitmap); + const auto pPdfBuffer + = static_cast(FPDFBitmap_GetBuffer(pPdfBitmap->getPointer())); + const int nStride = FPDFBitmap_GetStride(pPdfBitmap->getPointer()); for (size_t nRow = 0; nRow < nPageHeight; ++nRow) { ConstScanline pPdfLine = pPdfBuffer + (nStride * nRow); -- cgit