From 1d17a047db12530f28f4b5e22a9c5bd175af641f Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Thu, 16 Mar 2017 13:22:47 -0700 Subject: Introduce unique_ptr compatible deleters for FPDF types Pre-requisite for easily fixing some leaks in sample code, fuzzers, etc. Kill off some types completely unused in the C API. Change-Id: I67f0a5c6eef63d8e062ca4bc97c9db03970fe337 Reviewed-on: https://pdfium-review.googlesource.com/3095 Reviewed-by: dsinclair Commit-Queue: Tom Sepez --- BUILD.gn | 1 + public/cpp/fpdf_deleters.h | 41 +++++++++++++++ public/fpdfview.h | 4 -- samples/pdfium_test.cc | 123 ++++++++++++++++++++------------------------- 4 files changed, 96 insertions(+), 73 deletions(-) create mode 100644 public/cpp/fpdf_deleters.h diff --git a/BUILD.gn b/BUILD.gn index 70cb5baecb..1442cd114c 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -142,6 +142,7 @@ static_library("pdfium") { "fpdfsdk/fsdk_pauseadapter.h", "fpdfsdk/pdfsdk_fieldaction.cpp", "fpdfsdk/pdfsdk_fieldaction.h", + "public/cpp/fpdf_deleters.h", "public/fpdf_dataavail.h", "public/fpdf_doc.h", "public/fpdf_edit.h", diff --git a/public/cpp/fpdf_deleters.h b/public/cpp/fpdf_deleters.h new file mode 100644 index 0000000000..6754902a77 --- /dev/null +++ b/public/cpp/fpdf_deleters.h @@ -0,0 +1,41 @@ +// Copyright 2017 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PUBLIC_CPP_FPDF_DELETERS_H_ +#define PUBLIC_CPP_FPDF_DELETERS_H_ + +#include "public/fpdf_dataavail.h" +#include "public/fpdf_formfill.h" +#include "public/fpdf_text.h" +#include "public/fpdfview.h" + +// Custom deleters for using FPDF_* types with std::unique_ptr<>. + +struct FPDFAvailDeleter { + inline void operator()(FPDF_AVAIL avail) { FPDFAvail_Destroy(avail); } +}; + +struct FPDFBitmapDeleter { + inline void operator()(FPDF_BITMAP bitmap) { FPDFBitmap_Destroy(bitmap); } +}; + +struct FPDFDocumentDeleter { + inline void operator()(FPDF_DOCUMENT doc) { FPDF_CloseDocument(doc); } +}; + +struct FPDFFormHandleDeleter { + inline void operator()(FPDF_FORMHANDLE form) { + FPDFDOC_ExitFormFillEnvironment(form); + } +}; + +struct FPDFTextPageDeleter { + inline void operator()(FPDF_TEXTPAGE text) { FPDFText_ClosePage(text); } +}; + +struct FPDFPageDeleter { + inline void operator()(FPDF_PAGE page) { FPDF_ClosePage(page); } +}; + +#endif // PUBLIC_CPP_FPDF_DELETERS_H_ diff --git a/public/fpdfview.h b/public/fpdfview.h index 1c47a366bd..0ed9187f35 100644 --- a/public/fpdfview.h +++ b/public/fpdfview.h @@ -26,17 +26,13 @@ typedef void* FPDF_BITMAP; typedef void* FPDF_BOOKMARK; typedef void* FPDF_CLIPPATH; typedef void* FPDF_DEST; -typedef void* FPDF_DOCSCHHANDLE; typedef void* FPDF_DOCUMENT; typedef void* FPDF_FONT; -typedef void* FPDF_HMODULE; typedef void* FPDF_LINK; -typedef void* FPDF_MODULEMGR; typedef void* FPDF_PAGE; typedef void* FPDF_PAGELINK; typedef void* FPDF_PAGEOBJECT; // Page object(text, path, etc) typedef void* FPDF_PAGERANGE; -typedef void* FPDF_PATH; typedef void* FPDF_RECORDER; typedef void* FPDF_SCHHANDLE; typedef void* FPDF_STRUCTELEMENT; diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc index a0afd4d09c..c15a1a8648 100644 --- a/samples/pdfium_test.cc +++ b/samples/pdfium_test.cc @@ -18,6 +18,7 @@ #endif #include "core/fdrm/crypto/fx_crypt.h" +#include "public/cpp/fpdf_deleters.h" #include "public/fpdf_dataavail.h" #include "public/fpdf_edit.h" #include "public/fpdf_ext.h" @@ -95,10 +96,6 @@ struct FPDF_FORMFILLINFO_PDFiumTest : public FPDF_FORMFILLINFO { FPDF_FORMHANDLE form_handle; }; -struct AvailDeleter { - inline void operator()(FPDF_AVAIL avail) const { FPDFAvail_Destroy(avail); } -}; - static FPDF_FORMFILLINFO_PDFiumTest* ToPDFiumTestFormFillInfo( FPDF_FORMFILLINFO* form_fill_info) { return static_cast(form_fill_info); @@ -184,14 +181,11 @@ void WriteText(FPDF_PAGE page, const char* pdf_name, int num) { uint32_t bom = 0x0000FEFF; fwrite(&bom, sizeof(bom), 1, fp); - FPDF_TEXTPAGE textpage = FPDFText_LoadPage(page); - for (int i = 0; i < FPDFText_CountChars(textpage); i++) { - uint32_t c = FPDFText_GetUnicode(textpage, i); + std::unique_ptr textpage(FPDFText_LoadPage(page)); + for (int i = 0; i < FPDFText_CountChars(textpage.get()); i++) { + uint32_t c = FPDFText_GetUnicode(textpage.get(), i); fwrite(&c, sizeof(c), 1, fp); } - - FPDFText_ClosePage(textpage); - (void)fclose(fp); } @@ -609,7 +603,6 @@ FPDF_PAGE GetPageForIndex(FPDF_FORMFILLINFO* param, FPDF_FORMFILLINFO_PDFiumTest* form_fill_info = ToPDFiumTestFormFillInfo(param); auto& loaded_pages = form_fill_info->loaded_pages; - auto iter = loaded_pages.find(index); if (iter != loaded_pages.end()) return iter->second; @@ -619,47 +612,50 @@ FPDF_PAGE GetPageForIndex(FPDF_FORMFILLINFO* param, return nullptr; FPDF_FORMHANDLE& form_handle = form_fill_info->form_handle; - FORM_OnAfterLoadPage(page, form_handle); FORM_DoPageAAction(page, form_handle, FPDFPAGE_AACTION_OPEN); - loaded_pages[index] = page; return page; } bool RenderPage(const std::string& name, FPDF_DOCUMENT doc, - FPDF_FORMHANDLE& form, + FPDF_FORMHANDLE form, FPDF_FORMFILLINFO_PDFiumTest& form_fill_info, const int page_index, const Options& options, const std::string& events) { - FPDF_PAGE page = GetPageForIndex(&form_fill_info, doc, page_index); - if (!page) + std::unique_ptr page( + GetPageForIndex(&form_fill_info, doc, page_index)); + if (!page.get()) return false; - FPDF_TEXTPAGE text_page = FPDFText_LoadPage(page); - + std::unique_ptr text_page( + FPDFText_LoadPage(page.get())); if (options.send_events) - SendPageEvents(form, page, events); + SendPageEvents(form, page.get(), events); double scale = 1.0; if (!options.scale_factor_as_string.empty()) std::stringstream(options.scale_factor_as_string) >> scale; - int width = static_cast(FPDF_GetPageWidth(page) * scale); - int height = static_cast(FPDF_GetPageHeight(page) * scale); - int alpha = FPDFPage_HasTransparency(page) ? 1 : 0; - FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, alpha); + int width = static_cast(FPDF_GetPageWidth(page.get()) * scale); + int height = static_cast(FPDF_GetPageHeight(page.get()) * scale); + int alpha = FPDFPage_HasTransparency(page.get()) ? 1 : 0; + std::unique_ptr bitmap( + FPDFBitmap_Create(width, height, alpha)); + if (bitmap) { FPDF_DWORD fill_color = alpha ? 0x00000000 : 0xFFFFFFFF; - FPDFBitmap_FillRect(bitmap, 0, 0, width, height, fill_color); - FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, FPDF_ANNOT); + FPDFBitmap_FillRect(bitmap.get(), 0, 0, width, height, fill_color); + FPDF_RenderPageBitmap(bitmap.get(), page.get(), 0, 0, width, height, 0, + FPDF_ANNOT); - FPDF_FFLDraw(form, bitmap, page, 0, 0, width, height, 0, FPDF_ANNOT); - int stride = FPDFBitmap_GetStride(bitmap); + FPDF_FFLDraw(form, bitmap.get(), page.get(), 0, 0, width, height, 0, + FPDF_ANNOT); + int stride = FPDFBitmap_GetStride(bitmap.get()); const char* buffer = - reinterpret_cast(FPDFBitmap_GetBuffer(bitmap)); + reinterpret_cast(FPDFBitmap_GetBuffer(bitmap.get())); std::string&& image_file_name = ""; switch (options.output_format) { @@ -670,11 +666,11 @@ bool RenderPage(const std::string& name, break; case OUTPUT_EMF: - WriteEmf(page, name.c_str(), page_index); + WriteEmf(page.get(), name.c_str(), page_index); break; #endif case OUTPUT_TEXT: - WriteText(page, name.c_str(), page_index); + WriteText(page.get(), name.c_str(), page_index); break; case OUTPUT_PNG: @@ -691,8 +687,9 @@ bool RenderPage(const std::string& name, case OUTPUT_SKP: { std::unique_ptr recorder( reinterpret_cast( - FPDF_RenderPageSkp(page, width, height))); - FPDF_FFLRecord(form, recorder.get(), page, 0, 0, width, height, 0, 0); + FPDF_RenderPageSkp(page.get(), width, height))); + FPDF_FFLRecord(form, recorder.get(), page.get(), 0, 0, width, height, 0, + 0); image_file_name = WriteSkp(name.c_str(), page_index, recorder.get()); } break; #endif @@ -704,18 +701,13 @@ bool RenderPage(const std::string& name, // file. if (options.md5 && image_file_name != "") OutputMD5Hash(image_file_name.c_str(), buffer, stride * height); - - FPDFBitmap_Destroy(bitmap); } else { fprintf(stderr, "Page was too large to be rendered.\n"); } form_fill_info.loaded_pages.erase(page_index); - - FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_CLOSE); - FORM_OnBeforeClosePage(page, form); - FPDFText_ClosePage(text_page); - FPDF_ClosePage(page); + FORM_DoPageAAction(page.get(), form, FPDFPAGE_AACTION_CLOSE); + FORM_OnBeforeClosePage(page.get(), form); return !!bitmap; } @@ -758,35 +750,33 @@ void RenderPdf(const std::string& name, hints.version = 1; hints.AddSegment = Add_Segment; - FPDF_DOCUMENT doc; int nRet = PDF_DATA_NOTAVAIL; bool bIsLinearized = false; - FPDF_AVAIL pdf_avail = FPDFAvail_Create(&file_avail, &file_access); - std::unique_ptr scoped_pdf_avail_deleter(pdf_avail); + std::unique_ptr doc; + std::unique_ptr pdf_avail( + FPDFAvail_Create(&file_avail, &file_access)); - if (FPDFAvail_IsLinearized(pdf_avail) == PDF_LINEARIZED) { - doc = FPDFAvail_GetDocument(pdf_avail, nullptr); + if (FPDFAvail_IsLinearized(pdf_avail.get()) == PDF_LINEARIZED) { + doc.reset(FPDFAvail_GetDocument(pdf_avail.get(), nullptr)); if (doc) { while (nRet == PDF_DATA_NOTAVAIL) - nRet = FPDFAvail_IsDocAvail(pdf_avail, &hints); + nRet = FPDFAvail_IsDocAvail(pdf_avail.get(), &hints); if (nRet == PDF_DATA_ERROR) { fprintf(stderr, "Unknown error in checking if doc was available.\n"); - FPDF_CloseDocument(doc); return; } - nRet = FPDFAvail_IsFormAvail(pdf_avail, &hints); + nRet = FPDFAvail_IsFormAvail(pdf_avail.get(), &hints); if (nRet == PDF_FORM_ERROR || nRet == PDF_FORM_NOTAVAIL) { fprintf(stderr, "Error %d was returned in checking if form was available.\n", nRet); - FPDF_CloseDocument(doc); return; } bIsLinearized = true; } } else { - doc = FPDF_LoadCustomDocument(&file_access, nullptr); + doc.reset(FPDF_LoadCustomDocument(&file_access, nullptr)); } if (!doc) { @@ -818,29 +808,29 @@ void RenderPdf(const std::string& name, fprintf(stderr, "Unknown error %ld", err); } fprintf(stderr, ".\n"); - return; } - (void)FPDF_GetDocPermissions(doc); + (void)FPDF_GetDocPermissions(doc.get()); - FPDF_FORMHANDLE form = FPDFDOC_InitFormFillEnvironment(doc, &form_callbacks); - form_callbacks.form_handle = form; + std::unique_ptr form( + FPDFDOC_InitFormFillEnvironment(doc.get(), &form_callbacks)); + form_callbacks.form_handle = form.get(); #ifdef PDF_ENABLE_XFA int doc_type = DOCTYPE_PDF; - if (FPDF_HasXFAField(doc, &doc_type) && doc_type != DOCTYPE_PDF && - !FPDF_LoadXFA(doc)) { + if (FPDF_HasXFAField(doc.get(), &doc_type) && doc_type != DOCTYPE_PDF && + !FPDF_LoadXFA(doc.get())) { fprintf(stderr, "LoadXFA unsuccessful, continuing anyway.\n"); } #endif // PDF_ENABLE_XFA - FPDF_SetFormFieldHighlightColor(form, 0, 0xFFE4DD); - FPDF_SetFormFieldHighlightAlpha(form, 100); - FORM_DoDocumentJSAction(form); - FORM_DoDocumentOpenAction(form); + FPDF_SetFormFieldHighlightColor(form.get(), 0, 0xFFE4DD); + FPDF_SetFormFieldHighlightAlpha(form.get(), 100); + FORM_DoDocumentJSAction(form.get()); + FORM_DoDocumentOpenAction(form.get()); - int page_count = FPDF_GetPageCount(doc); + int page_count = FPDF_GetPageCount(doc.get()); int rendered_pages = 0; int bad_pages = 0; int first_page = options.pages ? options.first_page : 0; @@ -849,27 +839,22 @@ void RenderPdf(const std::string& name, if (bIsLinearized) { nRet = PDF_DATA_NOTAVAIL; while (nRet == PDF_DATA_NOTAVAIL) - nRet = FPDFAvail_IsPageAvail(pdf_avail, i, &hints); + nRet = FPDFAvail_IsPageAvail(pdf_avail.get(), i, &hints); if (nRet == PDF_DATA_ERROR) { fprintf(stderr, "Unknown error in checking if page %d is available.\n", i); - FPDFDOC_ExitFormFillEnvironment(form); - FPDF_CloseDocument(doc); return; } } - if (RenderPage(name, doc, form, form_callbacks, i, options, events)) + if (RenderPage(name, doc.get(), form.get(), form_callbacks, i, options, + events)) ++rendered_pages; else ++bad_pages; } - FORM_DoDocumentAAction(form, FPDFDOC_AACTION_WC); - - FPDFDOC_ExitFormFillEnvironment(form); - FPDF_CloseDocument(doc); - + FORM_DoDocumentAAction(form.get(), FPDFDOC_AACTION_WC); fprintf(stderr, "Rendered %d pages.\n", rendered_pages); if (bad_pages) fprintf(stderr, "Skipped %d bad pages.\n", bad_pages); -- cgit v1.2.3