Change |CPDF_Annot::m_pPopupAnnot| to UnownedPtr.
Fix destruction order to prevent dangling pointers.
Change-Id: I460e51681388a629cbd75afe994b8957b9922ab7
Reviewed-on: https://pdfium-review.googlesource.com/c/49690
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfdoc/cpdf_annot.h b/core/fpdfdoc/cpdf_annot.h
index c6999db..d4c2dd1 100644
--- a/core/fpdfdoc/cpdf_annot.h
+++ b/core/fpdfdoc/cpdf_annot.h
@@ -104,7 +104,7 @@
const CPDF_RenderOptions* pOptions);
CPDF_Form* GetAPForm(const CPDF_Page* pPage, AppearanceMode mode);
void SetOpenState(bool bOpenState) { m_bOpenState = bOpenState; }
- CPDF_Annot* GetPopupAnnot() const { return m_pPopupAnnot; }
+ CPDF_Annot* GetPopupAnnot() const { return m_pPopupAnnot.Get(); }
void SetPopupAnnot(CPDF_Annot* pAnnot) { m_pPopupAnnot = pAnnot; }
private:
@@ -119,13 +119,12 @@
UnownedPtr<CPDF_Document> const m_pDocument;
CPDF_Annot::Subtype m_nSubtype;
std::map<CPDF_Stream*, std::unique_ptr<CPDF_Form>> m_APMap;
+ // If non-null, then this is not a popup annotation.
+ UnownedPtr<CPDF_Annot> m_pPopupAnnot;
// |m_bOpenState| is only set for popup annotations.
bool m_bOpenState = false;
bool m_bHasGeneratedAP;
bool m_bIsTextMarkupAnnotation;
- // Not owned. If there is a valid pointer in |m_pPopupAnnot|,
- // then this annot is never a popup.
- CPDF_Annot* m_pPopupAnnot = nullptr;
};
// Get the AP in an annotation dict for a given appearance mode.
diff --git a/core/fpdfdoc/cpdf_annotlist.cpp b/core/fpdfdoc/cpdf_annotlist.cpp
index c37c9ef..5d22beb 100644
--- a/core/fpdfdoc/cpdf_annotlist.cpp
+++ b/core/fpdfdoc/cpdf_annotlist.cpp
@@ -196,8 +196,8 @@
}
}
- size_t nAnnotListSize = m_AnnotList.size();
- for (size_t i = 0; i < nAnnotListSize; ++i) {
+ m_nAnnotCount = m_AnnotList.size();
+ for (size_t i = 0; i < m_nAnnotCount; ++i) {
std::unique_ptr<CPDF_Annot> pPopupAnnot =
CreatePopupAnnot(m_pDocument.Get(), pPage, m_AnnotList[i].get());
if (pPopupAnnot)
@@ -205,7 +205,16 @@
}
}
-CPDF_AnnotList::~CPDF_AnnotList() = default;
+CPDF_AnnotList::~CPDF_AnnotList() {
+ // Move the pop-up annotations out of |m_AnnotList| into |popups|. Then
+ // destroy |m_AnnotList| first. This prevents dangling pointers to the pop-up
+ // annotations.
+ size_t nPopupCount = m_AnnotList.size() - m_nAnnotCount;
+ std::vector<std::unique_ptr<CPDF_Annot>> popups(nPopupCount);
+ for (size_t i = 0; i < nPopupCount; ++i)
+ popups[i] = std::move(m_AnnotList[m_nAnnotCount + i]);
+ m_AnnotList.clear();
+}
void CPDF_AnnotList::DisplayPass(CPDF_Page* pPage,
CFX_RenderDevice* pDevice,
diff --git a/core/fpdfdoc/cpdf_annotlist.h b/core/fpdfdoc/cpdf_annotlist.h
index 26cd96c..49a00e5 100644
--- a/core/fpdfdoc/cpdf_annotlist.h
+++ b/core/fpdfdoc/cpdf_annotlist.h
@@ -59,7 +59,11 @@
FX_RECT* clip_rect);
UnownedPtr<CPDF_Document> const m_pDocument;
+
+ // The first |m_nAnnotCount| elements are from the PDF itself. The rest are
+ // generated pop-up annotations.
std::vector<std::unique_ptr<CPDF_Annot>> m_AnnotList;
+ size_t m_nAnnotCount = 0;
};
#endif // CORE_FPDFDOC_CPDF_ANNOTLIST_H_