Add a Reset() method to unowned pointer.

Makes it consistent with retain pointer. Also document an
intentional difference between the two.

Change-Id: I90f59ff0e7ac040c2e909112d05b258eb9908924
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/59450
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcrt/retain_ptr.h b/core/fxcrt/retain_ptr.h
index 5cfc231..f69f764 100644
--- a/core/fxcrt/retain_ptr.h
+++ b/core/fxcrt/retain_ptr.h
@@ -70,6 +70,9 @@
     return *this;
   }
 
+  // Assigment from raw pointers is intentially not provided to make
+  // reference count churn more visible where possible.
+
   bool operator==(const RetainPtr& that) const { return Get() == that.Get(); }
   bool operator!=(const RetainPtr& that) const { return !(*this == that); }
 
diff --git a/core/fxcrt/unowned_ptr.h b/core/fxcrt/unowned_ptr.h
index f7a2354..7bbd937 100644
--- a/core/fxcrt/unowned_ptr.h
+++ b/core/fxcrt/unowned_ptr.h
@@ -59,16 +59,19 @@
 
   ~UnownedPtr() { ProbeForLowSeverityLifetimeIssue(); }
 
-  UnownedPtr& operator=(T* that) noexcept {
+  void Reset(T* obj = nullptr) {
     ProbeForLowSeverityLifetimeIssue();
-    m_pObj = that;
+    m_pObj = obj;
+  }
+
+  UnownedPtr& operator=(T* that) noexcept {
+    Reset(that);
     return *this;
   }
 
   UnownedPtr& operator=(const UnownedPtr& that) noexcept {
-    ProbeForLowSeverityLifetimeIssue();
     if (*this != that)
-      m_pObj = that.Get();
+      Reset(that.Get());
     return *this;
   }
 
diff --git a/core/fxcrt/unowned_ptr_unittest.cpp b/core/fxcrt/unowned_ptr_unittest.cpp
index 8d3c1b4..c125873 100644
--- a/core/fxcrt/unowned_ptr_unittest.cpp
+++ b/core/fxcrt/unowned_ptr_unittest.cpp
@@ -26,6 +26,15 @@
   }
 }
 
+void ResetDangling() {
+  auto ptr2 = pdfium::MakeUnique<Clink>();
+  {
+    auto ptr1 = pdfium::MakeUnique<Clink>();
+    ptr2->next_.Reset(ptr1.get());
+  }
+  ptr2->next_.Reset();
+}
+
 void AssignDangling() {
   auto ptr2 = pdfium::MakeUnique<Clink>();
   {
@@ -62,6 +71,23 @@
 #endif
 }
 
+TEST(UnownedPtr, ResetOk) {
+  auto ptr1 = pdfium::MakeUnique<Clink>();
+  {
+    auto ptr2 = pdfium::MakeUnique<Clink>();
+    ptr2->next_.Reset(ptr1.get());
+    ptr2->next_.Reset(nullptr);
+  }
+}
+
+TEST(UnownedPtr, ResetNotOk) {
+#if defined(ADDRESS_SANITIZER)
+  EXPECT_DEATH(ResetDangling(), "");
+#else
+  ResetDangling();
+#endif
+}
+
 TEST(UnownedPtr, AssignOk) {
   auto ptr1 = pdfium::MakeUnique<Clink>();
   {