Copy m_NewAddedNodes before iterating over it.
In turn, this exposes an issue where we might try and run node
script after FF env is gone (and along with it the JS environment).
Bug: chromium:927644
Change-Id: Ib6ef5cd9935bce852a0b02569173949ff73fdf7a
Reviewed-on: https://pdfium-review.googlesource.com/c/49694
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/xfa/fxfa/cxfa_ffdocview.cpp b/xfa/fxfa/cxfa_ffdocview.cpp
index 87835bb..b433562 100644
--- a/xfa/fxfa/cxfa_ffdocview.cpp
+++ b/xfa/fxfa/cxfa_ffdocview.cpp
@@ -6,6 +6,8 @@
#include "xfa/fxfa/cxfa_ffdocview.h"
+#include <utility>
+
#include "core/fxcrt/fx_extension.h"
#include "fxjs/xfa/cfxjse_engine.h"
#include "fxjs/xfa/cjx_object.h"
@@ -168,12 +170,16 @@
return;
LockUpdate();
- for (CXFA_Node* pNode : m_NewAddedNodes) {
- InitCalculate(pNode);
- InitValidate(pNode);
- ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true);
+ while (!m_NewAddedNodes.empty()) {
+ std::vector<CXFA_Node*> nodes = std::move(m_NewAddedNodes);
+ m_NewAddedNodes.clear();
+ for (CXFA_Node* pNode : nodes) {
+ InitCalculate(pNode);
+ InitValidate(pNode);
+ ExecEventActivityByDeepFirst(pNode, XFA_EVENT_Ready, true, true);
+ }
+ // May have created more newly added nodes, try again.
}
- m_NewAddedNodes.clear();
RunSubformIndexChange();
RunCalculateWidgets();
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp
index f9d26c3..df2abf1 100644
--- a/xfa/fxfa/parser/cxfa_node.cpp
+++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -2240,7 +2240,7 @@
bool first = true;
int32_t iRet = XFA_EVENTERROR_NotExist;
for (CXFA_Event* event : eventArray) {
- int32_t result = ProcessEvent(docView, event, pEventParam);
+ int32_t result = ProcessEvent(docView, iActivity, event, pEventParam);
if (first || result == XFA_EVENTERROR_Success)
iRet = result;
first = false;
@@ -2249,6 +2249,7 @@
}
int32_t CXFA_Node::ProcessEvent(CXFA_FFDocView* docView,
+ XFA_AttributeValue iActivity,
CXFA_Event* event,
CXFA_EventParam* pEventParam) {
if (!event)
@@ -2258,6 +2259,10 @@
case XFA_Element::Execute:
break;
case XFA_Element::Script:
+ if (iActivity == XFA_AttributeValue::DocClose) {
+ // Too late, scripting engine already gone.
+ return false;
+ }
return ExecuteScript(docView, event->GetScriptIfExists(), pEventParam);
case XFA_Element::SignData:
break;
diff --git a/xfa/fxfa/parser/cxfa_node.h b/xfa/fxfa/parser/cxfa_node.h
index a89a69f..0bd1bde 100644
--- a/xfa/fxfa/parser/cxfa_node.h
+++ b/xfa/fxfa/parser/cxfa_node.h
@@ -466,6 +466,7 @@
Optional<float> TryMaxWidth();
Optional<float> TryMaxHeight();
int32_t ProcessEvent(CXFA_FFDocView* docView,
+ XFA_AttributeValue iActivity,
CXFA_Event* event,
CXFA_EventParam* pEventParam);