Fix an UnownedPtr error in CXFA_FFTabOrderPageWidgetIterator. CPDFXFA_Page::GetNextXFAAnnot() and GetFirstOrLastXFAAnnot() can potentially trigger an UnownedPtr error in CXFA_FFTabOrderPageWidgetIterator. Fix the issue by using a RetainPtr to ensure the object in question has the right live time. This is a secondary issue from a previous bug report. Add a test case for that. Bug: chromium:980161 Change-Id: I895c3b6634aa0f7a68d2b44cc0307afc64716c78 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/70252 Reviewed-by: Tom Sepez <tsepez@chromium.org> Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/testing/resources/javascript/xfa_specific/bug_980161.evt b/testing/resources/javascript/xfa_specific/bug_980161.evt new file mode 100644 index 0000000..a5025fa --- /dev/null +++ b/testing/resources/javascript/xfa_specific/bug_980161.evt
@@ -0,0 +1,4 @@ +mousemove,50,50 +mousedown,left,50,50 +mouseup,left,50,50 +keycode,9
diff --git a/testing/resources/javascript/xfa_specific/bug_980161.in b/testing/resources/javascript/xfa_specific/bug_980161.in new file mode 100644 index 0000000..058444d --- /dev/null +++ b/testing/resources/javascript/xfa_specific/bug_980161.in
@@ -0,0 +1,55 @@ +{{header}} +{{include ../../xfa_catalog_1_0.fragment}} +{{include ../../xfa_object_2_0.fragment}} +{{include ../../xfa_preamble_3_0.fragment}} +{{include ../../xfa_config_4_0.fragment}} +{{object 5 0}} << + {{streamlen}} +>> +stream +<template xmlns="http://www.xfa.org/schema/xfa-template/2.6/"> + <subform layout="tb" locale="en_US" name="form1" restoreState="auto"> + <pageSet> + <pageArea id="Page1" name="Page1"> + <contentArea h="10.5in" w="8in" x="0.25in" y="0.25in"/> + <medium long="11in" short="8.5in" stock="letter"/> + </pageArea> + </pageSet> + <subform h="10.5in" w="8in"> + <field h="3mm" name="DropDownList1" w="3mm" x="0mm" y="1mm"> + <ui> + <choiceList/> + </ui> + <items save="1"> + <text>Single</text> + <text>Married</text> + <text>Other</text> + </items> + </field> + <field h="500.0001mm" name="DropDownList2" w="500.625mm" x="0mm" y="0mm"> + <ui> + <textEdit></textEdit> + </ui> + <traversal> + <traverse operation="next" ref="$xfa.(eval('xfa.host.setFocus(field_DropDownList1); xfa.template.remerge(); xfa.host.openList(field_DropDownList1);') == 0)"/> + </traversal> + </field> + </subform> + <event activity="docReady"> + <script contentType="application/x-javascript"> + field_DropDownList1 = xfa.resolveNode("xfa.form..DropDownList1"); + field_DropDownList2 = xfa.resolveNode("xfa.form..DropDownList2"); + xfa.host.setFocus(field_DropDownList2); + </script> + </event> + </subform> +</template> +endstream +endobj +{{include ../../xfa_locale_6_0.fragment}} +{{include ../../xfa_postamble_7_0.fragment}} +{{include ../../xfa_pages_8_0.fragment}} +{{xref}} +{{trailer}} +{{startxref}} +%%EOF
diff --git a/xfa/fxfa/cxfa_ffpageview.cpp b/xfa/fxfa/cxfa_ffpageview.cpp index 45a4ddc..3e3a7a4 100644 --- a/xfa/fxfa/cxfa_ffpageview.cpp +++ b/xfa/fxfa/cxfa_ffpageview.cpp
@@ -238,7 +238,7 @@ CXFA_FFTabOrderPageWidgetIterator::CXFA_FFTabOrderPageWidgetIterator( CXFA_FFPageView* pPageView, uint32_t dwFilter) - : m_pPageView(pPageView), + : m_pPageViewLayout(pPageView->GetLayoutItem()), m_dwFilter(dwFilter), m_bIgnoreRelevant(IsDocVersionBelow205(GetDocForPageView(pPageView))) { Reset(); @@ -442,7 +442,7 @@ void CXFA_FFTabOrderPageWidgetIterator::CreateSpaceOrderWidgetArray( std::vector<CXFA_FFWidget*>* WidgetArray) { - CXFA_LayoutItemIterator sIterator(m_pPageView->GetLayoutItem()); + CXFA_LayoutItemIterator sIterator(m_pPageViewLayout.Get()); auto pParam = std::make_unique<CXFA_TabParam>(nullptr); bool bCurrentItem = false; bool bContentArea = false;
diff --git a/xfa/fxfa/cxfa_ffpageview.h b/xfa/fxfa/cxfa_ffpageview.h index a4ecb3d..1025046 100644 --- a/xfa/fxfa/cxfa_ffpageview.h +++ b/xfa/fxfa/cxfa_ffpageview.h
@@ -108,7 +108,7 @@ bool bMasterPage); std::vector<RetainPtr<CXFA_ContentLayoutItem>> m_TabOrderWidgetArray; - UnownedPtr<CXFA_FFPageView> const m_pPageView; + RetainPtr<CXFA_ViewLayoutItem> const m_pPageViewLayout; const uint32_t m_dwFilter; int32_t m_iCurWidget = -1; const bool m_bIgnoreRelevant;