M71: Cover some more orphaning in cpdfsdk_baannot.cpp.

Bug: chromium:901654
Change-Id: Ie21106abe47d99638014574a6ec724ff06006508
Reviewed-on: https://pdfium-review.googlesource.com/c/45610
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
(cherry picked from commit 4534834b7c7b1fb5b7ce8954d630d45c82ee3d12)
Reviewed-on: https://pdfium-review.googlesource.com/c/46850
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_baannot.cpp b/fpdfsdk/cpdfsdk_baannot.cpp
index 5fe3411..ffff2bf 100644
--- a/fpdfsdk/cpdfsdk_baannot.cpp
+++ b/fpdfsdk/cpdfsdk_baannot.cpp
@@ -53,7 +53,9 @@
   ASSERT(rect.right - rect.left >= GetMinWidth());
   ASSERT(rect.top - rect.bottom >= GetMinHeight());
 
-  GetAnnotDict()->SetRectFor("Rect", rect);
+  CPDF_Dictionary* pDict = GetAnnotDict();
+  m_pAnnot->GetDocument()->AddOrphan(pDict->RemoveFor("Rect"));
+  pDict->SetRectFor("Rect", rect);
 }
 
 CFX_FloatRect CPDFSDK_BAAnnot::GetRect() const {
@@ -96,10 +98,10 @@
 }
 
 void CPDFSDK_BAAnnot::SetAnnotName(const WideString& sName) {
-  if (sName.IsEmpty())
-    GetAnnotDict()->RemoveFor("NM");
-  else
-    GetAnnotDict()->SetNewFor<CPDF_String>("NM", PDF_EncodeText(sName), false);
+  CPDF_Dictionary* pDict = GetAnnotDict();
+  m_pAnnot->GetDocument()->AddOrphan(pDict->RemoveFor("NM"));
+  if (!sName.IsEmpty())
+    pDict->SetNewFor<CPDF_String>("NM", PDF_EncodeText(sName), false);
 }
 
 WideString CPDFSDK_BAAnnot::GetAnnotName() const {
@@ -107,7 +109,9 @@
 }
 
 void CPDFSDK_BAAnnot::SetFlags(uint32_t nFlags) {
-  GetAnnotDict()->SetNewFor<CPDF_Number>("F", static_cast<int>(nFlags));
+  CPDF_Dictionary* pDict = GetAnnotDict();
+  m_pAnnot->GetDocument()->AddOrphan(pDict->RemoveFor("F"));
+  pDict->SetNewFor<CPDF_Number>("F", static_cast<int>(nFlags));
 }
 
 uint32_t CPDFSDK_BAAnnot::GetFlags() const {
@@ -115,10 +119,10 @@
 }
 
 void CPDFSDK_BAAnnot::SetAppState(const ByteString& str) {
-  if (str.IsEmpty())
-    GetAnnotDict()->RemoveFor("AS");
-  else
-    GetAnnotDict()->SetNewFor<CPDF_String>("AS", str, false);
+  CPDF_Dictionary* pDict = GetAnnotDict();
+  m_pAnnot->GetDocument()->AddOrphan(pDict->RemoveFor("AS"));
+  if (!str.IsEmpty())
+    pDict->SetNewFor<CPDF_String>("AS", str, false);
 }
 
 ByteString CPDFSDK_BAAnnot::GetAppState() const {
@@ -133,7 +137,7 @@
     CPDF_Dictionary* pBSDict = GetAnnotDict()->GetDictFor("BS");
     if (!pBSDict)
       pBSDict = GetAnnotDict()->SetNewFor<CPDF_Dictionary>("BS");
-
+    m_pAnnot->GetDocument()->AddOrphan(pBSDict->RemoveFor("W"));
     pBSDict->SetNewFor<CPDF_Number>("W", nWidth);
   }
 }
@@ -153,25 +157,28 @@
   if (!pBSDict)
     pBSDict = GetAnnotDict()->SetNewFor<CPDF_Dictionary>("BS");
 
+  const char* name = nullptr;
   switch (nStyle) {
     case BorderStyle::SOLID:
-      pBSDict->SetNewFor<CPDF_Name>("S", "S");
+      name = "S";
       break;
     case BorderStyle::DASH:
-      pBSDict->SetNewFor<CPDF_Name>("S", "D");
+      name = "D";
       break;
     case BorderStyle::BEVELED:
-      pBSDict->SetNewFor<CPDF_Name>("S", "B");
+      name = "B";
       break;
     case BorderStyle::INSET:
-      pBSDict->SetNewFor<CPDF_Name>("S", "I");
+      name = "I";
       break;
     case BorderStyle::UNDERLINE:
-      pBSDict->SetNewFor<CPDF_Name>("S", "U");
+      name = "U";
       break;
     default:
-      break;
+      return;
   }
+  m_pAnnot->GetDocument()->AddOrphan(pBSDict->RemoveFor("S"));
+  pBSDict->SetNewFor<CPDF_Name>("S", name);
 }
 
 BorderStyle CPDFSDK_BAAnnot::GetBorderStyle() const {
diff --git a/fpdfsdk/fpdf_formfill_embeddertest.cpp b/fpdfsdk/fpdf_formfill_embeddertest.cpp
index 30c2962..c76a7eb 100644
--- a/fpdfsdk/fpdf_formfill_embeddertest.cpp
+++ b/fpdfsdk/fpdf_formfill_embeddertest.cpp
@@ -399,6 +399,25 @@
   UnloadPage(page);
 }
 
+TEST_F(FPDFFormFillEmbeddertest, BUG_901654_2) {
+  EmbedderTestTimerHandlingDelegate delegate;
+  SetDelegate(&delegate);
+
+  EXPECT_TRUE(OpenDocument("bug_901654_2.pdf"));
+  FPDF_PAGE page = LoadPage(0);
+  ASSERT_TRUE(page);
+  DoOpenActions();
+  delegate.AdvanceTime(4000);
+
+  // Simulate a repaint.
+  {
+    ScopedFPDFBitmap bitmap(FPDFBitmap_Create(512, 512, 0));
+    FPDF_RenderPageBitmap_Start(bitmap.get(), page, 0, 0, 512, 512, 0, 0,
+                                nullptr);
+  }
+  UnloadPage(page);
+}
+
 class DoURIActionBlockedDelegate final : public EmbedderTest::Delegate {
  public:
   void DoURIAction(FPDF_BYTESTRING uri) override {
diff --git a/testing/resources/bug_901654_2.in b/testing/resources/bug_901654_2.in
new file mode 100644
index 0000000..a1fe2e1
--- /dev/null
+++ b/testing/resources/bug_901654_2.in
@@ -0,0 +1,75 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+  /OpenAction 8 0 R
+>>
+{{object 2 0}} <<
+  /Type /Pages
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 600 700]
+  /Resources 5 0 R
+  /Contents 4 0 R
+  /Annots [6 0 R]
+>>
+endobj
+{{object 4 0}} <<
+>>
+stream
+  /NM
+  scn
+  BT
+   /F1 20 Tf
+   50 50 Td
+   (Test) Tj
+  ET
+endstream
+endobj
+{{object 5 0}} <<
+   /Pattern 6 0 R
+   /Font <<F1 7 0 R>>
+>>
+endobj
+{{object 6 0}} <<
+  /FT /Tx
+  /Type /Annot
+  /Subtype /Widget
+  /T (txt1)
+  /NM <</PatternType 2 /Shading <</Test (a)>> >>
+  /F 4
+  /Rect [200 200 400 400]
+  /V (t)
+>>
+endobj
+{{object 7 0}} <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+>>
+endobj
+{{object 8 0}} <<
+  /Type /Action
+  /S /JavaScript
+  /JS 9 0 R
+>>
+endobj
+{{object 9 0}} <<
+>>
+stream
+function run() {
+  a = this.getAnnot(0,'');
+  a.name = 'newname';
+}
+app.setTimeOut('run()',3000);
+endstream
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bug_901654_2.pdf b/testing/resources/bug_901654_2.pdf
new file mode 100644
index 0000000..3e8bbfe
--- /dev/null
+++ b/testing/resources/bug_901654_2.pdf
@@ -0,0 +1,91 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+  /Type /Catalog
+  /Pages 2 0 R
+  /OpenAction 8 0 R
+>>
+2 0 obj <<
+  /Type /Pages
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+3 0 obj <<
+  /Type /Page
+  /Parent 2 0 R
+  /MediaBox [0 0 600 700]
+  /Resources 5 0 R
+  /Contents 4 0 R
+  /Annots [6 0 R]
+>>
+endobj
+4 0 obj <<
+>>
+stream
+  /NM
+  scn
+  BT
+   /F1 20 Tf
+   50 50 Td
+   (Test) Tj
+  ET
+endstream
+endobj
+5 0 obj <<
+   /Pattern 6 0 R
+   /Font <<F1 7 0 R>>
+>>
+endobj
+6 0 obj <<
+  /FT /Tx
+  /Type /Annot
+  /Subtype /Widget
+  /T (txt1)
+  /NM <</PatternType 2 /Shading <</Test (a)>> >>
+  /F 4
+  /Rect [200 200 400 400]
+  /V (t)
+>>
+endobj
+7 0 obj <<
+  /Type /Font
+  /Subtype /Type1
+  /BaseFont /Helvetica
+>>
+endobj
+8 0 obj <<
+  /Type /Action
+  /S /JavaScript
+  /JS 9 0 R
+>>
+endobj
+9 0 obj <<
+>>
+stream
+function run() {
+  a = this.getAnnot(0,'');
+  a.name = 'newname';
+}
+app.setTimeOut('run()',3000);
+endstream
+endobj
+xref
+0 10
+0000000000 65535 f 
+0000000015 00000 n 
+0000000081 00000 n 
+0000000144 00000 n 
+0000000276 00000 n 
+0000000374 00000 n 
+0000000435 00000 n 
+0000000603 00000 n 
+0000000679 00000 n 
+0000000745 00000 n 
+trailer <<
+  /Root 1 0 R
+  /Size 10
+>>
+startxref
+881
+%%EOF