Retain layout item in all CFXA_FF.*::Paste() method overrides.

Covers cases missed by
  https://pdfium-review.googlesource.com/c/pdfium/+/67170

Bug: chromium:1058653
Change-Id: I9ede1c49d26bd0c37b80415b1ef30e5d318f79ca
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/67270
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdf_formfill_embeddertest.cpp b/fpdfsdk/fpdf_formfill_embeddertest.cpp
index de891f7..3e09a0a 100644
--- a/fpdfsdk/fpdf_formfill_embeddertest.cpp
+++ b/fpdfsdk/fpdf_formfill_embeddertest.cpp
@@ -2554,19 +2554,34 @@
   CheckCanRedo(false);
 }
 
-class FPDFXFAFormEmbedderTest : public FPDFFormFillInteractiveEmbedderTest {
+class FPDFXFAFormBug1055869EmbedderTest
+    : public FPDFFormFillInteractiveEmbedderTest {
  protected:
-  FPDFXFAFormEmbedderTest() = default;
-  ~FPDFXFAFormEmbedderTest() override = default;
+  FPDFXFAFormBug1055869EmbedderTest() = default;
+  ~FPDFXFAFormBug1055869EmbedderTest() override = default;
 
   const char* GetDocumentName() const override { return "bug_1055869.pdf"; }
-
   int GetFormType() const override { return FORMTYPE_XFA_FULL; }
 };
 
-TEST_F(FPDFXFAFormEmbedderTest, Paste) {
-  CFX_PointF where(100, 100);
+TEST_F(FPDFXFAFormBug1055869EmbedderTest, Paste) {
   ScopedFPDFWideString text_to_insert = GetFPDFWideString(L"XYZ");
-  DoubleClickOnFormFieldAtPoint(where);
+  DoubleClickOnFormFieldAtPoint(CFX_PointF(100, 100));
+  FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
+}
+
+class FPDFXFAFormBug1058653EmbedderTest
+    : public FPDFFormFillInteractiveEmbedderTest {
+ protected:
+  FPDFXFAFormBug1058653EmbedderTest() = default;
+  ~FPDFXFAFormBug1058653EmbedderTest() override = default;
+
+  const char* GetDocumentName() const override { return "bug_1058653.pdf"; }
+  int GetFormType() const override { return FORMTYPE_XFA_FULL; }
+};
+
+TEST_F(FPDFXFAFormBug1058653EmbedderTest, Paste) {
+  ScopedFPDFWideString text_to_insert = GetFPDFWideString(L"");
+  DoubleClickOnFormFieldAtPoint(CFX_PointF(22, 22));
   FORM_ReplaceSelection(form_handle(), page(), text_to_insert.get());
 }
diff --git a/testing/resources/bug_1058653.in b/testing/resources/bug_1058653.in
new file mode 100644
index 0000000..5973c54
--- /dev/null
+++ b/testing/resources/bug_1058653.in
@@ -0,0 +1,73 @@
+{{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" name="subform2">
+      <field name="f1" h="10mm" w="10mm" x="20mm" y="20mm">
+        <ui>
+          <choiceList/>
+        </ui>
+        <items save="1">
+          <text>aaaaaaaaaa</text>
+        </items>
+      </field>
+      <subform name="f4" x="1mm" y="1mm">
+        <occur max="-1"/>
+        <field name="f2" h="350mm" w="200mm">
+          <ui>
+            <choiceList textEntry="1">
+            </choiceList>
+          </ui>
+          <items>
+                <text>Albania</text>
+                <text>Andorra</text>
+                <text>Armenia</text>
+          </items>
+          <event activity="change">
+            <script contentType="application/x-javascript">
+              a += 1;
+              if (a == 2) {
+                  c = xfa.resolveNode("xfa.form..f1");
+                  xfa.host.setFocus(c);
+                  d = xfa.resolveNode("xfa.form..f4");
+                  d.instanceManager.addInstance(1);
+                  d.instanceManager.removeInstance(0);
+                  xfa.host.openList(c);
+              }
+            </script>
+          </event>
+        </field>
+      </subform>
+    </subform>
+    <event activity="docReady">
+      <script contentType="application/x-javascript">
+        a = 0;
+        f2 = xfa.resolveNode("xfa.form..f2");
+        f2.rawValue = "minhtttttt";
+        xfa.host.setFocus(f2);
+      </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/testing/resources/bug_1058653.pdf b/testing/resources/bug_1058653.pdf
new file mode 100644
index 0000000..1c10793
--- /dev/null
+++ b/testing/resources/bug_1058653.pdf
@@ -0,0 +1,282 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /AcroForm 2 0 R
+  /Extensions <<
+    /ADBE <<
+      /BaseVersion /1.7
+      /ExtensionLevel 8
+    >>
+  >>
+  /NeedsRendering true
+  /Pages 8 0 R
+  /Type /Catalog
+>>
+endobj
+2 0 obj <<
+  /XFA [
+    (preamble)
+    3 0 R
+    (config)
+    4 0 R
+    (template)
+    5 0 R
+    (localeSet)
+    6 0 R
+    (postamble)
+    7 0 R
+  ]
+>>
+endobj
+3 0 obj <<
+  /Length 124
+>>
+stream
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/" timeStamp="2018-02-23T21:37:11Z" uuid="21482798-7bf0-40a4-bc5d-3cefdccf32b5">
+endstream
+endobj
+4 0 obj <<
+  /Length 642
+>>
+stream
+<config xmlns="http://www.xfa.org/schema/xci/3.0/">
+<agent name="designer">
+  <destination>pdf</destination>
+  <pdf>
+    <fontInfo/>
+  </pdf>
+</agent>
+<present>
+  <pdf>
+    <version>1.7</version>
+    <adobeExtensionLevel>8</adobeExtensionLevel>
+    <renderPolicy>client</renderPolicy>
+    <scriptModel>XFA</scriptModel>
+    <interactive>1</interactive>
+  </pdf>
+  <xdp>
+    <packets>*</packets>
+  </xdp>
+  <destination>pdf</destination>
+  <script>
+    <runScripts>server</runScripts>
+  </script>
+</present>
+<acrobat>
+  <acrobat7>
+    <dynamicRender>required</dynamicRender>
+  </acrobat7>
+  <validate>preSubmit</validate>
+</acrobat>
+</config>
+endstream
+endobj
+5 0 obj <<
+  /Length 1772
+>>
+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" name="subform2">
+      <field name="f1" h="10mm" w="10mm" x="20mm" y="20mm">
+        <ui>
+          <choiceList/>
+        </ui>
+        <items save="1">
+          <text>aaaaaaaaaa</text>
+        </items>
+      </field>
+      <subform name="f4" x="1mm" y="1mm">
+        <occur max="-1"/>
+        <field name="f2" h="350mm" w="200mm">
+          <ui>
+            <choiceList textEntry="1">
+            </choiceList>
+          </ui>
+          <items>
+                <text>Albania</text>
+                <text>Andorra</text>
+                <text>Armenia</text>
+          </items>
+          <event activity="change">
+            <script contentType="application/x-javascript">
+              a += 1;
+              if (a == 2) {
+                  c = xfa.resolveNode("xfa.form..f1");
+                  xfa.host.setFocus(c);
+                  d = xfa.resolveNode("xfa.form..f4");
+                  d.instanceManager.addInstance(1);
+                  d.instanceManager.removeInstance(0);
+                  xfa.host.openList(c);
+              }
+            </script>
+          </event>
+        </field>
+      </subform>
+    </subform>
+    <event activity="docReady">
+      <script contentType="application/x-javascript">
+        a = 0;
+        f2 = xfa.resolveNode("xfa.form..f2");
+        f2.rawValue = "minhtttttt";
+        xfa.host.setFocus(f2);
+      </script>
+    </event>
+  </subform>
+</template>
+endstream
+endobj
+6 0 obj <<
+  /Length 3455
+>>
+stream
+<localeSet xmlns="http://www.xfa.org/schema/xfa-locale-set/2.7/">
+  <locale name="en_US" desc="English (United States)">
+    <calendarSymbols name="gregorian">
+      <monthNames>
+        <month>January</month>
+        <month>February</month>
+        <month>March</month>
+        <month>April</month>
+        <month>May</month>
+        <month>June</month>
+        <month>July</month>
+        <month>August</month>
+        <month>September</month>
+        <month>October</month>
+        <month>November</month>
+        <month>December</month>
+      </monthNames>
+      <monthNames abbr="1">
+        <month>Jan</month>
+        <month>Feb</month>
+        <month>Mar</month>
+        <month>Apr</month>
+        <month>May</month>
+        <month>Jun</month>
+        <month>Jul</month>
+        <month>Aug</month>
+        <month>Sep</month>
+        <month>Oct</month>
+        <month>Nov</month>
+        <month>Dec</month>
+      </monthNames>
+      <dayNames>
+        <day>Sunday</day>
+        <day>Monday</day>
+        <day>Tuesday</day>
+        <day>Wednesday</day>
+        <day>Thursday</day>
+        <day>Friday</day>
+        <day>Saturday</day>
+      </dayNames>
+      <dayNames abbr="1">
+        <day>Sun</day>
+        <day>Mon</day>
+        <day>Tue</day>
+        <day>Wed</day>
+        <day>Thu</day>
+        <day>Fri</day>
+        <day>Sat</day>
+      </dayNames>
+      <meridiemNames>
+        <meridiem>AM</meridiem>
+        <meridiem>PM</meridiem>
+      </meridiemNames>
+      <eraNames>
+        <era>BC</era>
+        <era>AD</era>
+      </eraNames>
+    </calendarSymbols>
+    <datePatterns>
+      <datePattern name="full">EEEE, MMMM D, YYYY</datePattern>
+      <datePattern name="long">MMMM D, YYYY</datePattern>
+      <datePattern name="med">MMM D, YYYY</datePattern>
+      <datePattern name="short">M/D/YY</datePattern>
+    </datePatterns>
+    <timePatterns>
+      <timePattern name="full">h:MM:SS A Z</timePattern>
+      <timePattern name="long">h:MM:SS A Z</timePattern>
+      <timePattern name="med">h:MM:SS A</timePattern>
+      <timePattern name="short">h:MM A</timePattern>
+    </timePatterns>
+    <dateTimeSymbols>GyMdkHmsSEDFwWahKzZ</dateTimeSymbols>
+    <numberPatterns>
+      <numberPattern name="numeric">z,zz9.zzz</numberPattern>
+      <numberPattern name="currency">$z,zz9.99|($z,zz9.99)</numberPattern>
+      <numberPattern name="percent">z,zz9%</numberPattern>
+    </numberPatterns>
+    <numberSymbols>
+      <numberSymbol name="decimal">.</numberSymbol>
+      <numberSymbol name="grouping">,</numberSymbol>
+      <numberSymbol name="percent">%</numberSymbol>
+      <numberSymbol name="minus">-</numberSymbol>
+      <numberSymbol name="zero">0</numberSymbol>
+    </numberSymbols>
+    <currencySymbols>
+      <currencySymbol name="symbol">$</currencySymbol>
+      <currencySymbol name="isoname">USD</currencySymbol>
+      <currencySymbol name="decimal">.</currencySymbol>
+    </currencySymbols>
+    <typefaces>
+      <typeface name="Myriad Pro"/>
+      <typeface name="Minion Pro"/>
+      <typeface name="Courier Std"/>
+      <typeface name="Adobe Pi Std"/>
+      <typeface name="Adobe Hebrew"/>
+      <typeface name="Adobe Arabic"/>
+      <typeface name="Adobe Thai"/>
+      <typeface name="Kozuka Gothic Pro-VI M"/>
+      <typeface name="Kozuka Mincho Pro-VI R"/>
+      <typeface name="Adobe Ming Std L"/>
+      <typeface name="Adobe Song Std L"/>
+      <typeface name="Adobe Myungjo Std M"/>
+    </typefaces>
+  </locale>
+</localeSet>
+endstream
+endobj
+7 0 obj <<
+  /Length 11
+>>
+stream
+</xdp:xdp>
+endstream
+endobj
+8 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [9 0 R]
+>>
+endobj
+9 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 612 792]
+>>
+endobj
+xref
+0 10
+0000000000 65535 f 
+0000000015 00000 n 
+0000000199 00000 n 
+0000000358 00000 n 
+0000000534 00000 n 
+0000001228 00000 n 
+0000003053 00000 n 
+0000006561 00000 n 
+0000006623 00000 n 
+0000006686 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 10
+>>
+startxref
+6763
+%%EOF
diff --git a/xfa/fxfa/cxfa_ffcombobox.cpp b/xfa/fxfa/cxfa_ffcombobox.cpp
index bf00c57..6e25e62 100644
--- a/xfa/fxfa/cxfa_ffcombobox.cpp
+++ b/xfa/fxfa/cxfa_ffcombobox.cpp
@@ -232,16 +232,6 @@
          ToComboBox(GetNormalWidget())->EditCanRedo();
 }
 
-bool CXFA_FFComboBox::Undo() {
-  return m_pNode->IsChoiceListAllowTextEntry() &&
-         ToComboBox(GetNormalWidget())->EditUndo();
-}
-
-bool CXFA_FFComboBox::Redo() {
-  return m_pNode->IsChoiceListAllowTextEntry() &&
-         ToComboBox(GetNormalWidget())->EditRedo();
-}
-
 bool CXFA_FFComboBox::CanCopy() {
   return ToComboBox(GetNormalWidget())->EditCanCopy();
 }
@@ -259,11 +249,33 @@
   return ToComboBox(GetNormalWidget())->EditCanSelectAll();
 }
 
+bool CXFA_FFComboBox::Undo() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
+  return m_pNode->IsChoiceListAllowTextEntry() &&
+         ToComboBox(GetNormalWidget())->EditUndo();
+}
+
+bool CXFA_FFComboBox::Redo() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
+  return m_pNode->IsChoiceListAllowTextEntry() &&
+         ToComboBox(GetNormalWidget())->EditRedo();
+}
+
 Optional<WideString> CXFA_FFComboBox::Copy() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
   return ToComboBox(GetNormalWidget())->EditCopy();
 }
 
 Optional<WideString> CXFA_FFComboBox::Cut() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
   if (!m_pNode->IsChoiceListAllowTextEntry())
     return {};
 
@@ -271,19 +283,31 @@
 }
 
 bool CXFA_FFComboBox::Paste(const WideString& wsPaste) {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
   return m_pNode->IsChoiceListAllowTextEntry() &&
          ToComboBox(GetNormalWidget())->EditPaste(wsPaste);
 }
 
 void CXFA_FFComboBox::SelectAll() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
   ToComboBox(GetNormalWidget())->EditSelectAll();
 }
 
 void CXFA_FFComboBox::Delete() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
   ToComboBox(GetNormalWidget())->EditDelete();
 }
 
 void CXFA_FFComboBox::DeSelect() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
   ToComboBox(GetNormalWidget())->EditDeSelect();
 }
 
diff --git a/xfa/fxfa/cxfa_ffcombobox.h b/xfa/fxfa/cxfa_ffcombobox.h
index 3813b6e..3e14dc6 100644
--- a/xfa/fxfa/cxfa_ffcombobox.h
+++ b/xfa/fxfa/cxfa_ffcombobox.h
@@ -28,13 +28,12 @@
   bool OnKillFocus(CXFA_FFWidget* pNewWidget) override WARN_UNUSED_RESULT;
   bool CanUndo() override;
   bool CanRedo() override;
-  bool Undo() override;
-  bool Redo() override;
-
   bool CanCopy() override;
   bool CanCut() override;
   bool CanPaste() override;
   bool CanSelectAll() override;
+  bool Undo() override;
+  bool Redo() override;
   Optional<WideString> Copy() override;
   Optional<WideString> Cut() override;
   bool Paste(const WideString& wsPaste) override;
diff --git a/xfa/fxfa/cxfa_ffdatetimeedit.cpp b/xfa/fxfa/cxfa_ffdatetimeedit.cpp
index 68c4d3e..7a8e6e6 100644
--- a/xfa/fxfa/cxfa_ffdatetimeedit.cpp
+++ b/xfa/fxfa/cxfa_ffdatetimeedit.cpp
@@ -236,14 +236,6 @@
   return GetPickerWidget()->CanRedo();
 }
 
-bool CXFA_FFDateTimeEdit::Undo() {
-  return GetPickerWidget()->Undo();
-}
-
-bool CXFA_FFDateTimeEdit::Redo() {
-  return GetPickerWidget()->Redo();
-}
-
 bool CXFA_FFDateTimeEdit::CanCopy() {
   return GetPickerWidget()->HasSelection();
 }
@@ -266,23 +258,52 @@
   return GetPickerWidget()->Copy();
 }
 
+bool CXFA_FFDateTimeEdit::Undo() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
+  return GetPickerWidget()->Undo();
+}
+
+bool CXFA_FFDateTimeEdit::Redo() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
+  return GetPickerWidget()->Redo();
+}
+
 Optional<WideString> CXFA_FFDateTimeEdit::Cut() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
   return GetPickerWidget()->Cut();
 }
 
 bool CXFA_FFDateTimeEdit::Paste(const WideString& wsPaste) {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
   return GetPickerWidget()->Paste(wsPaste);
 }
 
 void CXFA_FFDateTimeEdit::SelectAll() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
   GetPickerWidget()->SelectAll();
 }
 
 void CXFA_FFDateTimeEdit::Delete() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
   GetPickerWidget()->ClearText();
 }
 
 void CXFA_FFDateTimeEdit::DeSelect() {
+  // Prevents destruction of the CXFA_ContentLayoutItem that owns |this|.
+  RetainPtr<CXFA_ContentLayoutItem> retain_layout(m_pLayoutItem.Get());
+
   GetPickerWidget()->ClearSelection();
 }
 
diff --git a/xfa/fxfa/cxfa_ffdatetimeedit.h b/xfa/fxfa/cxfa_ffdatetimeedit.h
index 5ba6867..bad5424 100644
--- a/xfa/fxfa/cxfa_ffdatetimeedit.h
+++ b/xfa/fxfa/cxfa_ffdatetimeedit.h
@@ -39,12 +39,12 @@
   // CXFA_FFWidget
   bool CanUndo() override;
   bool CanRedo() override;
-  bool Undo() override;
-  bool Redo() override;
   bool CanCopy() override;
   bool CanCut() override;
   bool CanPaste() override;
   bool CanSelectAll() override;
+  bool Undo() override;
+  bool Redo() override;
   Optional<WideString> Copy() override;
   Optional<WideString> Cut() override;
   bool Paste(const WideString& wsPaste) override;