Change `CPDFSDK_PageView::m_SDKAnnotArray` to store std::unique_ptrs.
Instead of storing raw pointers and carefully managing them, store
std::unique_ptrs.
Change-Id: I1162eeee615af939f71f541452649f36a214b000
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/92113
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_pageview.cpp b/fpdfsdk/cpdfsdk_pageview.cpp
index 00f73f0..08ce6a3 100644
--- a/fpdfsdk/cpdfsdk_pageview.cpp
+++ b/fpdfsdk/cpdfsdk_pageview.cpp
@@ -7,6 +7,7 @@
#include "fpdfsdk/cpdfsdk_pageview.h"
#include <memory>
+#include <utility>
#include <vector>
#include "core/fpdfapi/parser/cpdf_dictionary.h"
@@ -15,6 +16,7 @@
#include "core/fpdfdoc/cpdf_annotlist.h"
#include "core/fpdfdoc/cpdf_interactiveform.h"
#include "core/fxcrt/autorestorer.h"
+#include "core/fxcrt/stl_util.h"
#include "fpdfsdk/cpdfsdk_annot.h"
#include "fpdfsdk/cpdfsdk_annotiteration.h"
#include "fpdfsdk/cpdfsdk_annotiterator.h"
@@ -53,8 +55,9 @@
m_page->AsPDFPage()->SetView(nullptr);
}
- for (CPDFSDK_Annot* pAnnot : m_SDKAnnotArray)
- delete pAnnot;
+ // Manually reset elements to ensure they are deleted in order.
+ for (std::unique_ptr<CPDFSDK_Annot>& pAnnot : m_SDKAnnotArray)
+ pAnnot.reset();
m_SDKAnnotArray.clear();
m_pAnnotList.reset();
@@ -127,9 +130,7 @@
pAnnotHandler->NewAnnotForXFA(pPDFAnnot, this);
DCHECK(pNewAnnot);
pSDKAnnot = pNewAnnot.get();
- // TODO(thestig): See if |m_SDKAnnotArray|, which takes ownership of
- // |pNewAnnot|, can hold std::unique_ptrs instead of raw pointers.
- m_SDKAnnotArray.push_back(pNewAnnot.release());
+ m_SDKAnnotArray.push_back(std::move(pNewAnnot));
return pSDKAnnot;
}
@@ -151,11 +152,12 @@
m_pFormFillEnv->KillFocusAnnot({}); // May invoke JS, invalidating pAnnot.
if (pObserved) {
- std::unique_ptr<CPDFSDK_Annot> to_be_deleted(pObserved.Get());
+ fxcrt::FakeUniquePtr<const CPDFSDK_Annot> fake_unique_annot(pAnnot);
+ auto it = std::find(m_SDKAnnotArray.begin(), m_SDKAnnotArray.end(),
+ fake_unique_annot);
+ if (it != m_SDKAnnotArray.end())
+ m_SDKAnnotArray.erase(it);
}
- auto it = std::find(m_SDKAnnotArray.begin(), m_SDKAnnotArray.end(), pAnnot);
- if (it != m_SDKAnnotArray.end())
- m_SDKAnnotArray.erase(it);
if (m_pCaptureWidget.Get() == pAnnot)
m_pCaptureWidget.Reset();
@@ -179,11 +181,19 @@
return m_pFormFillEnv->GetInteractiveForm();
}
+std::vector<CPDFSDK_Annot*> CPDFSDK_PageView::GetAnnotList() const {
+ std::vector<CPDFSDK_Annot*> list;
+ list.reserve(m_SDKAnnotArray.size());
+ for (const std::unique_ptr<CPDFSDK_Annot>& elem : m_SDKAnnotArray)
+ list.push_back(elem.get());
+ return list;
+}
+
CPDFSDK_Annot* CPDFSDK_PageView::GetAnnotByDict(CPDF_Dictionary* pDict) {
- for (CPDFSDK_Annot* pAnnot : m_SDKAnnotArray) {
+ for (std::unique_ptr<CPDFSDK_Annot>& pAnnot : m_SDKAnnotArray) {
CPDF_Annot* pPDFAnnot = pAnnot->GetPDFAnnot();
if (pPDFAnnot && pPDFAnnot->GetAnnotDict() == pDict)
- return pAnnot;
+ return pAnnot.get();
}
return nullptr;
}
@@ -193,10 +203,10 @@
if (!pWidget)
return nullptr;
- for (CPDFSDK_Annot* pAnnot : m_SDKAnnotArray) {
- CPDFXFA_Widget* pCurrentWidget = ToXFAWidget(pAnnot);
+ for (std::unique_ptr<CPDFSDK_Annot>& pAnnot : m_SDKAnnotArray) {
+ CPDFXFA_Widget* pCurrentWidget = ToXFAWidget(pAnnot.get());
if (pCurrentWidget && pCurrentWidget->GetXFAFFWidget() == pWidget)
- return pAnnot;
+ return pAnnot.get();
}
return nullptr;
}
@@ -596,7 +606,7 @@
pAnnotHandlerMgr->NewAnnotForXFA(pXFAAnnot, this);
DCHECK(pNewAnnot);
CPDFSDK_Annot* pAnnot = pNewAnnot.get();
- m_SDKAnnotArray.push_back(pNewAnnot.release());
+ m_SDKAnnotArray.push_back(std::move(pNewAnnot));
pAnnotHandlerMgr->Annot_OnLoad(pAnnot);
}
return;
@@ -619,8 +629,8 @@
pAnnotHandlerMgr->NewAnnot(pPDFAnnot, this);
if (!pAnnot)
continue;
- m_SDKAnnotArray.push_back(pAnnot.release());
- pAnnotHandlerMgr->Annot_OnLoad(m_SDKAnnotArray.back());
+ m_SDKAnnotArray.push_back(std::move(pAnnot));
+ pAnnotHandlerMgr->Annot_OnLoad(m_SDKAnnotArray.back().get());
}
}
@@ -660,7 +670,8 @@
bool CPDFSDK_PageView::IsValidSDKAnnot(const CPDFSDK_Annot* p) const {
if (!p)
return false;
- return pdfium::Contains(m_SDKAnnotArray, p);
+ fxcrt::FakeUniquePtr<const CPDFSDK_Annot> fake_unique_p(p);
+ return pdfium::Contains(m_SDKAnnotArray, fake_unique_p);
}
CPDFSDK_Annot* CPDFSDK_PageView::GetFocusAnnot() {
diff --git a/fpdfsdk/cpdfsdk_pageview.h b/fpdfsdk/cpdfsdk_pageview.h
index c10ee66..da1532c 100644
--- a/fpdfsdk/cpdfsdk_pageview.h
+++ b/fpdfsdk/cpdfsdk_pageview.h
@@ -49,9 +49,7 @@
bool IsValidAnnot(const CPDF_Annot* p) const;
bool IsValidSDKAnnot(const CPDFSDK_Annot* p) const;
- const std::vector<CPDFSDK_Annot*>& GetAnnotList() const {
- return m_SDKAnnotArray;
- }
+ std::vector<CPDFSDK_Annot*> GetAnnotList() const;
CPDFSDK_Annot* GetAnnotByDict(CPDF_Dictionary* pDict);
#ifdef PDF_ENABLE_XFA
@@ -128,7 +126,7 @@
CFX_Matrix m_curMatrix;
UnownedPtr<IPDF_Page> const m_page;
std::unique_ptr<CPDF_AnnotList> m_pAnnotList;
- std::vector<CPDFSDK_Annot*> m_SDKAnnotArray;
+ std::vector<std::unique_ptr<CPDFSDK_Annot>> m_SDKAnnotArray;
UnownedPtr<CPDFSDK_FormFillEnvironment> const m_pFormFillEnv;
ObservedPtr<CPDFSDK_Annot> m_pCaptureWidget;
RetainPtr<CPDF_Page> m_pOwnsPage;