Cleanup tiling and shading patterns in correct order

When a Shading is created we have both a ShadingPattern and a
ShadingObject. The ShadingPattern is a ref-counted object that is stored
in the CPDF_DocPageData. The ShadingObject, when we have a tiling
pattern parent, is stored in the CPDF_Form of the tiling pattern.

Currently during destruction it is possible for the ShadingPattern to
get cleaned up before the ShadingObject which causes the UnownedPtr
probe to fire. This CL loops over all patterns and for each Tiling
pattern forces the CPDF_Form to get cleared. This then removes the
ShadingObject before we remove the ShadingPattern.

Bug: chromium:728992
Change-Id: Ife65607aa97f69440b03028981b5575b1e297093
Reviewed-on: https://pdfium-review.googlesource.com/6651
Commit-Queue: dsinclair <dsinclair@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Nicolás Peña <npm@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_docpagedata.cpp b/core/fpdfapi/page/cpdf_docpagedata.cpp
index 4438006..71143d0 100644
--- a/core/fpdfapi/page/cpdf_docpagedata.cpp
+++ b/core/fpdfapi/page/cpdf_docpagedata.cpp
@@ -52,11 +52,26 @@
 void CPDF_DocPageData::Clear(bool bForceRelease) {
   m_bForceClear = bForceRelease;
 
+  // This is needed because if |bForceRelease| is true we will destroy any
+  // pattern we see regardless of the ref-count. The tiling pattern owns a
+  // Form object which owns a ShadingObject. The ShadingObject has an unowned
+  // pointer to a ShadingPattern. The ShadingPattern is owned by the
+  // DocPageData. So, we loop through and clear any tiling patterns before we
+  // do the same for any shading patterns, otherwise we may free the
+  // ShadingPattern before the ShadingObject and trigger an unowned pointer
+  // probe warning.
+  for (auto& it : m_PatternMap) {
+    CPDF_CountedPattern* ptData = it.second;
+    if (!ptData->get() || !ptData->get()->AsTilingPattern())
+      continue;
+    if (bForceRelease || ptData->use_count() < 2)
+      ptData->clear();
+  }
+
   for (auto& it : m_PatternMap) {
     CPDF_CountedPattern* ptData = it.second;
     if (!ptData->get())
       continue;
-
     if (bForceRelease || ptData->use_count() < 2)
       ptData->clear();
   }
@@ -65,7 +80,6 @@
     CPDF_CountedFont* fontData = it.second;
     if (!fontData->get())
       continue;
-
     if (bForceRelease || fontData->use_count() < 2) {
       fontData->clear();
     }
@@ -75,7 +89,6 @@
     CPDF_CountedColorSpace* csData = it.second;
     if (!csData->get())
       continue;
-
     if (bForceRelease || csData->use_count() < 2) {
       csData->get()->Release();
       csData->reset(nullptr);
diff --git a/core/fpdfapi/page/cpdf_shadingobject.cpp b/core/fpdfapi/page/cpdf_shadingobject.cpp
index 5454380..8a61161 100644
--- a/core/fpdfapi/page/cpdf_shadingobject.cpp
+++ b/core/fpdfapi/page/cpdf_shadingobject.cpp
@@ -6,7 +6,6 @@
 
 #include "core/fpdfapi/page/cpdf_shadingobject.h"
 
-#include "core/fpdfapi/page/cpdf_docpagedata.h"
 #include "core/fpdfapi/page/cpdf_shadingpattern.h"
 #include "core/fpdfapi/parser/cpdf_document.h"