Observe CXFA_FFWidget across UpdateFWLData() calls.
It may reenter JS and mutate the page.
Bug: chromium:1038000, chromium:995081
Change-Id: I14a4fdb7e4f6a499c9713bfe02f1cda2d3b5e32e
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/64531
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/xfa/fxfa/cxfa_ffcombobox.cpp b/xfa/fxfa/cxfa_ffcombobox.cpp
index 0336d28..fd485db 100644
--- a/xfa/fxfa/cxfa_ffcombobox.cpp
+++ b/xfa/fxfa/cxfa_ffcombobox.cpp
@@ -107,10 +107,11 @@
}
bool CXFA_FFComboBox::OnKillFocus(CXFA_FFWidget* pNewWidget) {
+ ObservedPtr<CXFA_FFWidget> pNewWatched(pNewWidget);
if (!ProcessCommittedData())
UpdateFWLData();
- return CXFA_FFField::OnKillFocus(pNewWidget);
+ return pNewWatched && CXFA_FFField::OnKillFocus(pNewWatched.Get());
}
void CXFA_FFComboBox::OpenDropDownList() {
diff --git a/xfa/fxfa/cxfa_ffdocview.cpp b/xfa/fxfa/cxfa_ffdocview.cpp
index ccf17bf..31141bf 100644
--- a/xfa/fxfa/cxfa_ffdocview.cpp
+++ b/xfa/fxfa/cxfa_ffdocview.cpp
@@ -196,14 +196,21 @@
void CXFA_FFDocView::UpdateUIDisplay(CXFA_Node* pNode, CXFA_FFWidget* pExcept) {
CXFA_FFWidget* pWidget = GetWidgetForNode(pNode);
- for (; pWidget; pWidget = pWidget->GetNextFFWidget()) {
+ CXFA_FFWidget* pNext = nullptr;
+ for (; pWidget; pWidget = pNext) {
+ pNext = pWidget->GetNextFFWidget();
if (pWidget == pExcept || !pWidget->IsLoaded() ||
(pNode->GetFFWidgetType() != XFA_FFWidgetType::kCheckButton &&
pWidget->IsFocused())) {
continue;
}
- pWidget->UpdateFWLData();
- pWidget->InvalidateRect();
+ ObservedPtr<CXFA_FFWidget> pWatched(pWidget);
+ ObservedPtr<CXFA_FFWidget> pWatchedNext(pNext);
+ pWatched->UpdateFWLData();
+ if (pWatched)
+ pWatched->InvalidateRect();
+ if (!pWatchedNext)
+ break;
}
}
@@ -285,6 +292,7 @@
if (pNewFocus == m_pFocusWidget)
return false;
+ ObservedPtr<CXFA_FFWidget> pNewWatched(pNewFocus);
if (m_pFocusWidget) {
CXFA_ContentLayoutItem* pItem = m_pFocusWidget->GetLayoutItem();
if (pItem->TestStatusBits(XFA_WidgetStatus_Visible) &&
@@ -296,22 +304,23 @@
}
}
if (m_pFocusWidget) {
- if (!m_pFocusWidget->OnKillFocus(pNewFocus))
+ if (!m_pFocusWidget->OnKillFocus(pNewWatched.Get()))
return false;
}
- if (pNewFocus) {
- if (pNewFocus->GetLayoutItem()->TestStatusBits(XFA_WidgetStatus_Visible)) {
- if (!pNewFocus->IsLoaded())
- pNewFocus->LoadWidget();
- if (!pNewFocus->OnSetFocus(m_pFocusWidget.Get()))
- pNewFocus = nullptr;
+ if (pNewWatched) {
+ if (pNewWatched->GetLayoutItem()->TestStatusBits(
+ XFA_WidgetStatus_Visible)) {
+ if (!pNewWatched->IsLoaded())
+ pNewWatched->LoadWidget();
+ if (!pNewWatched->OnSetFocus(m_pFocusWidget.Get()))
+ pNewWatched.Reset();
}
}
- if (pNewFocus) {
- CXFA_Node* node = pNewFocus->GetNode();
+ if (pNewWatched) {
+ CXFA_Node* node = pNewWatched->GetNode();
m_pFocusNode = node->IsWidgetReady() ? node : nullptr;
- m_pFocusWidget.Reset(pNewFocus);
+ m_pFocusWidget.Reset(pNewWatched.Get());
} else {
m_pFocusNode = nullptr;
m_pFocusWidget.Reset();
@@ -321,9 +330,7 @@
}
void CXFA_FFDocView::SetFocusNode(CXFA_Node* node) {
- CXFA_FFWidget* pNewFocus = nullptr;
- if (node)
- pNewFocus = GetWidgetForNode(node);
+ CXFA_FFWidget* pNewFocus = node ? GetWidgetForNode(node) : nullptr;
if (!SetFocus(pNewFocus))
return;
diff --git a/xfa/fxfa/cxfa_fffield.cpp b/xfa/fxfa/cxfa_fffield.cpp
index 767ef2a..217fe2c 100644
--- a/xfa/fxfa/cxfa_fffield.cpp
+++ b/xfa/fxfa/cxfa_fffield.cpp
@@ -506,13 +506,14 @@
}
bool CXFA_FFField::OnKillFocus(CXFA_FFWidget* pNewWidget) {
+ ObservedPtr<CXFA_FFWidget> pNewWatched(pNewWidget);
if (GetNormalWidget()) {
SendMessageToFWLWidget(
pdfium::MakeUnique<CFWL_MessageKillFocus>(nullptr, GetNormalWidget()));
GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus_Focused);
InvalidateRect();
}
- return CXFA_FFWidget::OnKillFocus(pNewWidget);
+ return pNewWatched && CXFA_FFWidget::OnKillFocus(pNewWatched.Get());
}
bool CXFA_FFField::OnKeyDown(uint32_t dwKeyCode, uint32_t dwFlags) {
diff --git a/xfa/fxfa/cxfa_fflistbox.cpp b/xfa/fxfa/cxfa_fflistbox.cpp
index 38e6b1a..ede1bc5 100644
--- a/xfa/fxfa/cxfa_fflistbox.cpp
+++ b/xfa/fxfa/cxfa_fflistbox.cpp
@@ -71,10 +71,11 @@
}
bool CXFA_FFListBox::OnKillFocus(CXFA_FFWidget* pNewFocus) {
+ ObservedPtr<CXFA_FFWidget> pWatched(pNewFocus);
if (!ProcessCommittedData())
UpdateFWLData();
- return CXFA_FFField::OnKillFocus(pNewFocus);
+ return pWatched && CXFA_FFField::OnKillFocus(pWatched.Get());
}
bool CXFA_FFListBox::CommitData() {
diff --git a/xfa/fxfa/cxfa_fftextedit.cpp b/xfa/fxfa/cxfa_fftextedit.cpp
index cf3eb61..d9af369 100644
--- a/xfa/fxfa/cxfa_fftextedit.cpp
+++ b/xfa/fxfa/cxfa_fftextedit.cpp
@@ -152,13 +152,14 @@
}
bool CXFA_FFTextEdit::OnSetFocus(CXFA_FFWidget* pOldWidget) {
+ ObservedPtr<CXFA_FFWidget> pWatched(pOldWidget);
GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus_TextEditValueChanged);
if (!IsFocused()) {
GetLayoutItem()->SetStatusBits(XFA_WidgetStatus_Focused);
UpdateFWLData();
InvalidateRect();
}
- if (!CXFA_FFWidget::OnSetFocus(pOldWidget))
+ if (!CXFA_FFWidget::OnSetFocus(pWatched.Get()))
return false;
SendMessageToFWLWidget(
@@ -168,6 +169,7 @@
}
bool CXFA_FFTextEdit::OnKillFocus(CXFA_FFWidget* pNewWidget) {
+ ObservedPtr<CXFA_FFWidget> pWatched(pNewWidget);
SendMessageToFWLWidget(
pdfium::MakeUnique<CFWL_MessageKillFocus>(nullptr, GetNormalWidget()));
@@ -177,7 +179,7 @@
UpdateFWLData();
InvalidateRect();
- if (!CXFA_FFWidget::OnKillFocus(pNewWidget))
+ if (!CXFA_FFWidget::OnKillFocus(pWatched.Get()))
return false;
GetLayoutItem()->ClearStatusBits(XFA_WidgetStatus_TextEditValueChanged);