Update googleurl to e18f5d8d2d81b4b81b88b169267f2b13c128ab21

This is the Chromium version from Tue Aug 2 04:36:47 2022 +0000

Change-Id: I493e33ee8470a7a4b46703ac7987a0749c9c1d33
diff --git a/AUTHORS b/AUTHORS
index b81d16f..abd2e53 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -58,6 +58,7 @@
 Alex Henrie <alexhenrie24@gmail.com>
 Alex Scheele <alexscheele@gmail.com>
 Alexander Douglas <agdoug@amazon.com>
+Alexander Forrence <alex.forrence@gmail.com>
 Alexander Guettler <alexander@guettler.io>
 Alexander Rezepkin <etu@vivaldi.net>
 Alexander Shalamov <alexander.shalamov@intel.com>
@@ -182,6 +183,7 @@
 Brook Hong <hzgmaxwell@gmail.com>
 Bruno Calvignac <bruno@flock.com>
 Bruno de Oliveira Abinader <brunoabinader@gmail.com>
+Bruno Pitrus <brunopitrus@hotmail.com>
 Bruno Roy <brusi_roy@hotmail.com>
 Bryan Donlan <bdonlan@gmail.com>
 Bryce Thomas <bryct@amazon.com>
@@ -515,6 +517,7 @@
 Jeado Ko <haibane84@gmail.com>
 Jeffrey C <jeffreyca16@gmail.com>
 Jeffrey Yeung <jeffrey.yeung@poly.com>
+Jelle Bleyaert <jellebley@gmail.com>
 Jeong A Shin <jeonga@khu.ac.kr>
 Jeongeun Kim <je_julie.kim@samsung.com>
 Jeongmin Kim <kimwjdalsl@gmail.com>
@@ -534,6 +537,7 @@
 Jiahe Zhang <jiahe.zhang@intel.com>
 Jiajia Qin <jiajia.qin@intel.com>
 Jiajie Hu <jiajie.hu@intel.com>
+Jiangzhen Hou <houjiangzhen@360.cn>
 Jianjun Zhu <jianjun.zhu@intel.com>
 Jianneng Zhong <muzuiget@gmail.com>
 Jiawei Shao <jiawei.shao@intel.com>
@@ -911,6 +915,7 @@
 Peng Hu <penghu@tencent.com>
 Peng Jiang <leiyi.jp@gmail.com>
 Peng Xinchao <pxinchao@gmail.com>
+Peng Zhou <zhoupeng.1996@bytedance.com>
 Peng-Yu Chen <pengyu@libstarrify.so>
 Pei Wang <wangpei@uniontech.com>
 Peter Bright <drpizza@quiscalusmexicanus.org>
@@ -942,6 +947,7 @@
 Preeti Nayak <preeti.nayak@samsung.com>
 Pritam Nikam <pritam.nikam@samsung.com>
 Puttaraju R <puttaraju.r@samsung.com>
+Qi Tiezheng <qitiezheng@360.cn>
 Qi Yang <qi1988.yang@samsung.com>
 Qiang Zeng <zengqiang1@huawei.com>
 Qiankun Miao <qiankun.miao@intel.com>
@@ -979,6 +985,7 @@
 Rene Ladan <r.c.ladan@gmail.com>
 Richard Baranyi <lordprotector@gmail.com>
 Richard Li <richard.li@intel.com>
+Richard Smith <happyercat@gmail.com>
 Rijubrata Bhaumik <rijubrata.bhaumik@intel.com>
 Riku Voipio <riku.voipio@linaro.org>
 Rob Buis <rob.buis@samsung.com>
@@ -1046,6 +1053,7 @@
 Satoshi Matsuzaki <satoshi.matsuzaki@gmail.com>
 Satyajit Sahu <satyajit.sahu@amd.com>
 Sayan Nayak <sayan.nayak@samsung.com>
+Sayan Sivakumaran <sivakusayan@gmail.com>
 Scott D Phillips <scott.d.phillips@intel.com>
 Sean Bryant <sean@cyberwang.net>
 Sean DuBois <seaduboi@amazon.com>
@@ -1109,6 +1117,8 @@
 Sohom Datta <sohom.datta@learner.manipal.edu>
 Sohom Datta <dattasohom1@gmail.com>
 Song Fangzhen <songfangzhen@bytedance.com>
+Song Qinglin <songql@dingdao.com>
+Song Qinglin <songqinglin@gmail.com>
 Song YeWen <ffmpeg@gmail.com>
 Sooho Park <sooho1000@gmail.com>
 Soojung Choi <crystal2840@gmail.com>
@@ -1390,6 +1400,7 @@
 Macadamian <*@macadamian.com>
 Mail.ru Group <*@corp.mail.ru>
 Make Positive Provar Limited <*@provartesting.com>
+Mc Zeng <zengmcong@gmail.com>
 Mediatek <*@mediatek.com>
 Microsoft <*@microsoft.com>
 MIPS Technologies, Inc. <*@mips.com>
@@ -1426,5 +1437,6 @@
 Wacom <*@wacom.com>
 Xperi Corporation <*@xperi.com>
 Yandex LLC <*@yandex-team.ru>
+Zuckjet <zuckjet@gmail.com>
 # Please DO NOT APPEND here. See comments at the top of the file.
 # END organizations section.
diff --git a/base/compiler_specific.h b/base/compiler_specific.h
index 12e09b5..5719020 100644
--- a/base/compiler_specific.h
+++ b/base/compiler_specific.h
@@ -170,6 +170,8 @@
 #endif
 
 // DISABLE_CFI_ICALL -- Disable Control Flow Integrity indirect call checks.
+// Security Note: if you just need to allow calling of dlsym functions use
+// DISABLE_CFI_DLSYM.
 #if !defined(DISABLE_CFI_ICALL)
 #if BUILDFLAG(IS_WIN)
 // Windows also needs __declspec(guard(nocf)).
@@ -182,6 +184,21 @@
 #define DISABLE_CFI_ICALL
 #endif
 
+// DISABLE_CFI_DLSYM -- applies DISABLE_CFI_ICALL on platforms where dlsym
+// functions must be called. Retains CFI checks on platforms where loaded
+// modules participate in CFI (e.g. Windows).
+#if !defined(DISABLE_CFI_DLSYM)
+#if BUILDFLAG(IS_WIN)
+// Windows modules register functions when loaded so can be checked by CFG.
+#define DISABLE_CFI_DLSYM
+#else
+#define DISABLE_CFI_DLSYM DISABLE_CFI_ICALL
+#endif
+#endif
+#if !defined(DISABLE_CFI_DLSYM)
+#define DISABLE_CFI_DLSYM
+#endif
+
 // Macro useful for writing cross-platform function pointers.
 #if !defined(CDECL)
 #if BUILDFLAG(IS_WIN)
diff --git a/base/debug/crash_logging.cc b/base/debug/crash_logging.cc
index a6e3719..124a31f 100644
--- a/base/debug/crash_logging.cc
+++ b/base/debug/crash_logging.cc
@@ -4,8 +4,10 @@
 
 #include "base/debug/crash_logging.h"
 
-namespace gurl_base {
-namespace debug {
+#include "base/strings/string_piece.h"
+#include "build/build_config.h"
+
+namespace gurl_base::debug {
 
 namespace {
 
@@ -18,6 +20,24 @@
   if (!g_crash_key_impl)
     return nullptr;
 
+    // TODO(https://crbug.com/1341077): It would be great if the DCHECKs below
+    // could also be enabled on Android, but debugging tryjob failures was a bit
+    // difficult... :-/
+#if GURL_DCHECK_IS_ON() && !BUILDFLAG(IS_ANDROID)
+  gurl_base::StringPiece name_piece = name;
+
+  // Some `CrashKeyImplementation`s reserve certain characters and disallow
+  // using them in crash key names.  See also https://crbug.com/1341077.
+  GURL_DCHECK_EQ(gurl_base::StringPiece::npos, name_piece.find(':'))
+      << "; name_piece = " << name_piece;
+
+  // Some `CrashKeyImplementation`s support only short crash key names (e.g. see
+  // the GURL_DCHECK in crash_reporter::internal::CrashKeyStringImpl::Set).
+  // Enforcing this restrictions here ensures that crash keys will work for all
+  // `CrashKeyStringImpl`s.
+  GURL_DCHECK_LT(name_piece.size(), 40u);
+#endif
+
   return g_crash_key_impl->Allocate(name, value_length);
 }
 
@@ -60,5 +80,4 @@
   g_crash_key_impl = impl.release();
 }
 
-}  // namespace debug
-}  // namespace base
+}  // namespace gurl_base::debug
diff --git a/base/debug/crash_logging.h b/base/debug/crash_logging.h
index 98f40c1..417d227 100644
--- a/base/debug/crash_logging.h
+++ b/base/debug/crash_logging.h
@@ -69,6 +69,7 @@
   Size32 = 32,
   Size64 = 64,
   Size256 = 256,
+  Size1024 = 1024,
 };
 
 struct CrashKeyString;
@@ -159,6 +160,10 @@
   SCOPED_CRASH_KEY_STRING_INTERNAL(category, name, __COUNTER__, (data), \
                                    ::gurl_base::debug::CrashKeySize::Size256)
 
+#define SCOPED_CRASH_KEY_STRING1024(category, name, data)               \
+  SCOPED_CRASH_KEY_STRING_INTERNAL(category, name, __COUNTER__, (data), \
+                                   ::gurl_base::debug::CrashKeySize::Size1024)
+
 #define SCOPED_CRASH_KEY_BOOL(category, name, data)                       \
   static_assert(std::is_same<std::decay_t<decltype(data)>, bool>::value,  \
                 "SCOPED_CRASH_KEY_BOOL must be passed a boolean value."); \
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h
index 0b378f4..c10a65d 100644
--- a/base/memory/raw_ptr.h
+++ b/base/memory/raw_ptr.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include <climits>
 #include <cstddef>
 #include <functional>
 #include <type_traits>
@@ -142,7 +143,7 @@
 // MTECheckedPtr has no business with the topmost bits reserved for the
 // tag used by true ARM MTE, so we strip it out here.
 constexpr uintptr_t kTagMask =
-    ~kAddressMask & partition_alloc::internal::kMemTagUnmask;
+    ~kAddressMask & partition_alloc::internal::kPtrUntagMask;
 
 constexpr int kTopBitShift = 63;
 constexpr uintptr_t kTopBit = 1ull << kTopBitShift;
@@ -156,19 +157,20 @@
   // Checks if the necessary support is enabled in PartitionAlloc for `ptr`.
   template <typename T>
   static ALWAYS_INLINE bool EnabledForPtr(T* ptr) {
-    auto as_uintptr =
-        partition_alloc::internal::UnmaskPtr(reinterpret_cast<uintptr_t>(ptr));
+    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this class
+    // is responsible for handling the software MTE tag.
+    auto addr = partition_alloc::UntagPtr(ptr);
     // MTECheckedPtr algorithms work only when memory is
     // allocated by PartitionAlloc, from normal buckets pool.
     //
     // TODO(crbug.com/1307514): Allow direct-map buckets.
-    return partition_alloc::IsManagedByPartitionAlloc(as_uintptr) &&
-           partition_alloc::internal::IsManagedByNormalBuckets(as_uintptr);
+    return partition_alloc::IsManagedByPartitionAlloc(addr) &&
+           partition_alloc::internal::IsManagedByNormalBuckets(addr);
   }
 
-  // Returns pointer to the tag that protects are pointed by |ptr|.
-  static ALWAYS_INLINE void* TagPointer(uintptr_t ptr) {
-    return partition_alloc::PartitionTagPointer(ptr);
+  // Returns pointer to the tag that protects are pointed by |addr|.
+  static ALWAYS_INLINE void* TagPointer(uintptr_t addr) {
+    return partition_alloc::PartitionTagPointer(addr);
   }
 };
 
@@ -183,13 +185,15 @@
   // Wraps a pointer, and returns its uintptr_t representation.
   template <typename T>
   static ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
-    uintptr_t addr = reinterpret_cast<uintptr_t>(ptr);
+    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
+    // function is responsible for adding the software MTE tag.
+    uintptr_t addr = partition_alloc::UntagPtr(ptr);
     GURL_DCHECK_EQ(ExtractTag(addr), 0ull);
 
     // Return a not-wrapped |addr|, if it's either nullptr or if the protection
     // for this pointer is disabled.
     if (!PartitionAllocSupport::EnabledForPtr(ptr)) {
-      return reinterpret_cast<T*>(addr);
+      return ptr;
     }
 
     // Read the tag and place it in the top bits of the address.
@@ -201,7 +205,10 @@
 
     tag <<= kValidAddressBits;
     addr |= tag;
-    return reinterpret_cast<T*>(addr);
+    // See the disambiguation comment above.
+    // TODO(kdlee): Ensure that ptr's hardware MTE tag is preserved.
+    // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
+    return static_cast<T*>(partition_alloc::internal::TagAddr(addr));
   }
 
   // Notifies the allocator when a wrapped pointer is being removed or replaced.
@@ -213,7 +220,9 @@
   // hasn't been freed. The function is allowed to crash on nullptr.
   template <typename T>
   static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
-    uintptr_t wrapped_addr = reinterpret_cast<uintptr_t>(wrapped_ptr);
+    // Disambiguation: UntagPtr removes the hardware MTE tag, whereas this
+    // function is responsible for removing the software MTE tag.
+    uintptr_t wrapped_addr = partition_alloc::UntagPtr(wrapped_ptr);
     uintptr_t tag = ExtractTag(wrapped_addr);
     if (tag > 0) {
       // Read the tag provided by PartitionAlloc.
@@ -226,7 +235,11 @@
               PartitionAllocSupport::TagPointer(ExtractAddress(wrapped_addr)));
       if (UNLIKELY(tag != read_tag))
         IMMEDIATE_CRASH();
-      return reinterpret_cast<T*>(ExtractAddress(wrapped_addr));
+      // See the disambiguation comment above.
+      // TODO(kdlee): Ensure that ptr's hardware MTE tag is preserved.
+      // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
+      return static_cast<T*>(
+          partition_alloc::internal::TagAddr(ExtractAddress(wrapped_addr)));
     }
     return wrapped_ptr;
   }
@@ -283,8 +296,12 @@
 
   template <typename T>
   static ALWAYS_INLINE T* ExtractPtr(T* wrapped_ptr) {
-    return reinterpret_cast<T*>(
-        ExtractAddress(reinterpret_cast<uintptr_t>(wrapped_ptr)));
+    // Disambiguation: UntagPtr/TagAddr handle the hardware MTE tag, whereas
+    // this function is responsible for removing the software MTE tag.
+    // TODO(kdlee): Ensure that wrapped_ptr's hardware MTE tag is preserved.
+    // TODO(kdlee): Ensure that hardware and software MTE tags don't conflict.
+    return static_cast<T*>(partition_alloc::internal::TagAddr(
+        ExtractAddress(partition_alloc::UntagPtr(wrapped_ptr))));
   }
 
   static ALWAYS_INLINE uintptr_t ExtractTag(uintptr_t wrapped_ptr) {
@@ -362,7 +379,7 @@
   // Wraps a pointer.
   template <typename T>
   static ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
-    uintptr_t address = reinterpret_cast<uintptr_t>(ptr);
+    uintptr_t address = partition_alloc::UntagPtr(ptr);
     if (IsSupportedAndNotNull(address)) {
 #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
       GURL_CHECK(ptr != nullptr);
@@ -382,7 +399,7 @@
   // Notifies the allocator when a wrapped pointer is being removed or replaced.
   template <typename T>
   static ALWAYS_INLINE void ReleaseWrappedPtr(T* wrapped_ptr) {
-    uintptr_t address = reinterpret_cast<uintptr_t>(wrapped_ptr);
+    uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr);
     if (IsSupportedAndNotNull(address)) {
 #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
       GURL_CHECK(wrapped_ptr != nullptr);
@@ -403,7 +420,7 @@
   template <typename T>
   static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
 #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-    uintptr_t address = reinterpret_cast<uintptr_t>(wrapped_ptr);
+    uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr);
     if (IsSupportedAndNotNull(address)) {
       GURL_CHECK(wrapped_ptr != nullptr);
       GURL_CHECK(IsPointeeAlive(address));
@@ -441,14 +458,43 @@
             typename Z,
             typename = std::enable_if_t<offset_type<Z>, void>>
   static ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
-#if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
-    uintptr_t address = reinterpret_cast<uintptr_t>(wrapped_ptr);
+#if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
+    // First check if the new address lands within the same allocation
+    // (end-of-allocation address is ok too). It has a non-trivial cost, but
+    // it's cheaper and more secure than the previous implementation that
+    // rewrapped the pointer (wrapped the new pointer and unwrapped the old
+    // one).
+    uintptr_t address = partition_alloc::UntagPtr(wrapped_ptr);
     if (IsSupportedAndNotNull(address))
-      GURL_CHECK(IsValidDelta(address, delta_elems * sizeof(T)));
+      GURL_CHECK(IsValidDelta(address, delta_elems * static_cast<Z>(sizeof(T))));
+    return wrapped_ptr + delta_elems;
+#else
+    // In the "before allocation" mode, on 32-bit, we can run into a problem
+    // that the end-of-allocation address could fall out of "GigaCage", if this
+    // is the last slot of the super page, thus pointing to the guard page. This
+    // mean the ref-count won't be decreased when the pointer is released
+    // (leak).
+    //
+    // We could possibly solve it in a few different ways:
+    // - Add the trailing guard page to "GigaCage", but we'd have to think very
+    //   hard if this doesn't create another hole.
+    // - Add an address adjustment to "GigaCage" check, similar as the one in
+    //   PartitionAllocGetSlotStartInBRPPool(), but that seems fragile, not to
+    //   mention adding an extra instruction to an inlined hot path.
+    // - Let the leak happen, since it should a very rare condition.
+    // - Go back to the previous solution of rewrapping the pointer, but that
+    //   had an issue of losing protection in case the pointer ever gets shifter
+    //   before the end of allocation.
+    //
+    // We decided to cross that bridge once we get there... if we ever get
+    // there. Currently there are no plans to switch back to the "before
+    // allocation" mode.
+    //
+    // This problem doesn't exist in the "previous slot" mode, or any mode that
+    // involves putting extras after the allocation, because the
+    // end-of-allocation address belongs to the same slot.
+    static_assert(false);
 #endif
-    T* new_wrapped_ptr = WrapRawPtr(wrapped_ptr + delta_elems);
-    ReleaseWrappedPtr(wrapped_ptr);
-    return new_wrapped_ptr;
   }
 
   // Returns a copy of a wrapped pointer, without making an assertion on whether
@@ -564,6 +610,71 @@
       void const volatile* ptr);
 };
 
+template <class Super>
+struct RawPtrCountingImplWrapperForTest : public Super {
+  template <typename T>
+  static ALWAYS_INLINE T* WrapRawPtr(T* ptr) {
+    ++wrap_raw_ptr_cnt;
+    return Super::WrapRawPtr(ptr);
+  }
+
+  template <typename T>
+  static ALWAYS_INLINE void ReleaseWrappedPtr(T* ptr) {
+    ++release_wrapped_ptr_cnt;
+    Super::ReleaseWrappedPtr(ptr);
+  }
+
+  template <typename T>
+  static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) {
+    ++get_for_dereference_cnt;
+    return Super::SafelyUnwrapPtrForDereference(wrapped_ptr);
+  }
+
+  template <typename T>
+  static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) {
+    ++get_for_extraction_cnt;
+    return Super::SafelyUnwrapPtrForExtraction(wrapped_ptr);
+  }
+
+  template <typename T>
+  static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) {
+    ++get_for_comparison_cnt;
+    return Super::UnsafelyUnwrapPtrForComparison(wrapped_ptr);
+  }
+
+  static ALWAYS_INLINE void IncrementSwapCountForTest() {
+    ++wrapped_ptr_swap_cnt;
+  }
+
+  static ALWAYS_INLINE void IncrementLessCountForTest() {
+    ++wrapped_ptr_less_cnt;
+  }
+
+  static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {
+    ++pointer_to_member_operator_cnt;
+  }
+
+  static void ClearCounters() {
+    wrap_raw_ptr_cnt = 0;
+    release_wrapped_ptr_cnt = 0;
+    get_for_dereference_cnt = 0;
+    get_for_extraction_cnt = 0;
+    get_for_comparison_cnt = 0;
+    wrapped_ptr_swap_cnt = 0;
+    wrapped_ptr_less_cnt = 0;
+    pointer_to_member_operator_cnt = 0;
+  }
+
+  static inline int wrap_raw_ptr_cnt = INT_MIN;
+  static inline int release_wrapped_ptr_cnt = INT_MIN;
+  static inline int get_for_dereference_cnt = INT_MIN;
+  static inline int get_for_extraction_cnt = INT_MIN;
+  static inline int get_for_comparison_cnt = INT_MIN;
+  static inline int wrapped_ptr_swap_cnt = INT_MIN;
+  static inline int wrapped_ptr_less_cnt = INT_MIN;
+  static inline int pointer_to_member_operator_cnt = INT_MIN;
+};
+
 }  // namespace internal
 
 namespace raw_ptr_traits {
@@ -603,6 +714,16 @@
   static constexpr bool value = false;
 };
 
+// IsRawPtrCountingImpl<T>::value answers whether T is a specialization of
+// RawPtrCountingImplWrapperForTest, to know whether Impl is for testing
+// purposes.
+template <typename T>
+struct IsRawPtrCountingImpl : std::false_type {};
+
+template <typename T>
+struct IsRawPtrCountingImpl<internal::RawPtrCountingImplWrapperForTest<T>>
+    : std::true_type {};
+
 #if __OBJC__
 // raw_ptr<T> is not compatible with pointers to Objective-C classes for a
 // multitude of reasons. They may fail to compile in many cases, and wouldn't
@@ -690,6 +811,11 @@
 
 template <typename T, typename Impl = DefaultRawPtrImpl>
 class TRIVIAL_ABI GSL_POINTER raw_ptr {
+  using DanglingRawPtr = std::conditional_t<
+      raw_ptr_traits::IsRawPtrCountingImpl<Impl>::value,
+      raw_ptr<T, internal::RawPtrCountingImplWrapperForTest<RawPtrMayDangle>>,
+      raw_ptr<T, RawPtrMayDangle>>;
+
  public:
   static_assert(raw_ptr_traits::IsSupportedType<T>::value,
                 "raw_ptr<T> doesn't work with this kind of pointee type T");
@@ -706,15 +832,23 @@
     p.wrapped_ptr_ = nullptr;
   }
 
-  ALWAYS_INLINE raw_ptr& operator=(const raw_ptr& p) {
+  ALWAYS_INLINE raw_ptr& operator=(const raw_ptr& p) noexcept {
     // Duplicate before releasing, in case the pointer is assigned to itself.
+    //
+    // Unlike the move version of this operator, don't add |this != &p| branch,
+    // for performance reasons. Even though Duplicate() is not cheap, we
+    // practically never assign a raw_ptr<T> to itself. We suspect that a
+    // cumulative cost of a conditional branch, even if always correctly
+    // predicted, would exceed that.
     T* new_ptr = Impl::Duplicate(p.wrapped_ptr_);
     Impl::ReleaseWrappedPtr(wrapped_ptr_);
     wrapped_ptr_ = new_ptr;
     return *this;
   }
 
-  ALWAYS_INLINE raw_ptr& operator=(raw_ptr&& p) {
+  ALWAYS_INLINE raw_ptr& operator=(raw_ptr&& p) noexcept {
+    // Unlike the the copy version of this operator, this branch is necessaty
+    // for correctness.
     if (LIKELY(this != &p)) {
       Impl::ReleaseWrappedPtr(wrapped_ptr_);
       wrapped_ptr_ = p.wrapped_ptr_;
@@ -748,7 +882,7 @@
   ALWAYS_INLINE raw_ptr& operator=(const raw_ptr&) noexcept = default;
   ALWAYS_INLINE raw_ptr& operator=(raw_ptr&&) noexcept = default;
 
-  ALWAYS_INLINE ~raw_ptr() = default;
+  ALWAYS_INLINE ~raw_ptr() noexcept = default;
 
 #endif  // BUILDFLAG(USE_BACKUP_REF_PTR)
 
@@ -895,26 +1029,39 @@
   // during the free operation, which will lead to taking the slower path that
   // involves quarantine.
   ALWAYS_INLINE void ClearAndDelete() noexcept {
-#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
-    // We cannot directly `delete` a wrapped pointer, since the tag bits
-    // atop will lead PA totally astray.
-    T* ptr = Impl::SafelyUnwrapPtrForExtraction(wrapped_ptr_);
-#else
-    T* ptr = wrapped_ptr_;
-#endif  // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
-    operator=(nullptr);
-    delete ptr;
+    delete GetForExtractionAndReset();
   }
   ALWAYS_INLINE void ClearAndDeleteArray() noexcept {
-#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
-    // We cannot directly `delete` a wrapped pointer, since the tag bits
-    // atop will lead PA totally astray.
-    T* ptr = Impl::SafelyUnwrapPtrForExtraction(wrapped_ptr_);
-#else
-    T* ptr = wrapped_ptr_;
-#endif  // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
-    operator=(nullptr);
-    delete[] ptr;
+    delete[] GetForExtractionAndReset();
+  }
+
+  // Clear the underlying pointer and return another raw_ptr instance
+  // that is allowed to dangle.
+  // This can be useful in cases such as:
+  // ```
+  //  ptr.ExtractAsDangling()->SelfDestroy();
+  // ```
+  // ```
+  //  c_style_api_do_something_and_destroy(ptr.ExtractAsDangling());
+  // ```
+  // NOTE, avoid using this method as it indicates an error-prone memory
+  // ownership pattern. If possible, use smart pointers like std::unique_ptr<>
+  // instead of raw_ptr<>.
+  ALWAYS_INLINE DanglingRawPtr ExtractAsDangling() noexcept {
+    if constexpr (std::is_same_v<
+                      typename std::remove_reference<decltype(*this)>::type,
+                      DanglingRawPtr>) {
+      DanglingRawPtr res(std::move(*this));
+      // Not all implementation clear the source pointer on move, so do it
+      // here just in case. Should be cheap.
+      operator=(nullptr);
+      return res;
+    } else {
+      T* ptr = GetForExtraction();
+      DanglingRawPtr res(ptr);
+      operator=(nullptr);
+      return res;
+    }
   }
 
   // Comparison operators between raw_ptr and raw_ptr<U>/U*/std::nullptr_t.
@@ -1049,6 +1196,12 @@
     return Impl::UnsafelyUnwrapPtrForComparison(wrapped_ptr_);
   }
 
+  ALWAYS_INLINE T* GetForExtractionAndReset() {
+    T* ptr = GetForExtraction();
+    operator=(nullptr);
+    return ptr;
+  }
+
   T* wrapped_ptr_;
 
   template <typename U, typename V>
diff --git a/base/strings/abseil_string_number_conversions.h b/base/strings/abseil_string_number_conversions.h
index 85d6d29..c709d34 100644
--- a/base/strings/abseil_string_number_conversions.h
+++ b/base/strings/abseil_string_number_conversions.h
@@ -7,10 +7,7 @@
 
 #include "polyfills/base/base_export.h"
 #include "base/strings/string_piece_forward.h"
-
-namespace absl {
-class uint128;
-}  // namespace absl
+#include "absl/numeric/int128.h"
 
 namespace gurl_base {
 
diff --git a/base/strings/string_util.h b/base/strings/string_util.h
index c3224f1..282d4a8 100644
--- a/base/strings/string_util.h
+++ b/base/strings/string_util.h
@@ -395,6 +395,10 @@
   return c >= '0' && c <= '9';
 }
 template <typename Char>
+inline bool IsAsciiAlphaNumeric(Char c) {
+  return IsAsciiAlpha(c) || IsAsciiDigit(c);
+}
+template <typename Char>
 inline bool IsAsciiPrintable(Char c) {
   return c >= ' ' && c <= '~';
 }
diff --git a/base/strings/string_util_internal.h b/base/strings/string_util_internal.h
index 8608eba..cc92e0d 100644
--- a/base/strings/string_util_internal.h
+++ b/base/strings/string_util_internal.h
@@ -536,7 +536,7 @@
     const std::vector<std::basic_string<CharT>>& subst,
     std::vector<size_t>* offsets) {
   size_t substitutions = subst.size();
-  GURL_DCHECK_LT(substitutions, 10U);
+  GURL_DCHECK_LT(substitutions, 11U);
 
   size_t sub_length = 0;
   for (const auto& cur : subst)
@@ -558,7 +558,8 @@
           --i;
         } else {
           if (*i < '1' || *i > '9') {
-            GURL_DLOG(ERROR) << "Invalid placeholder: $" << *i;
+            GURL_DLOG(ERROR) << "Invalid placeholder: $"
+                        << std::basic_string<CharT>(1, *i);
             continue;
           }
           size_t index = static_cast<size_t>(*i - '1');
diff --git a/base/strings/utf_string_conversion_utils.cc b/base/strings/utf_string_conversion_utils.cc
index 3ddcc7b..ffeeb6c 100644
--- a/base/strings/utf_string_conversion_utils.cc
+++ b/base/strings/utf_string_conversion_utils.cc
@@ -57,7 +57,7 @@
                           size_t* char_index,
                           base_icu::UChar32* code_point) {
   // Conversion is easy since the source is 32-bit.
-  *code_point = src[*char_index];
+  *code_point = static_cast<base_icu::UChar32>(src[*char_index]);
 
   // Validate the value.
   return IsValidCodepoint(*code_point);
diff --git a/base/strings/utf_string_conversions.cc b/base/strings/utf_string_conversions.cc
index 2124231..683b339 100644
--- a/base/strings/utf_string_conversions.cc
+++ b/base/strings/utf_string_conversions.cc
@@ -88,7 +88,7 @@
 void UnicodeAppendUnsafe(Char* out,
                          size_t* size,
                          base_icu::UChar32 code_point) {
-  out[(*size)++] = code_point;
+  out[(*size)++] = static_cast<Char>(code_point);
 }
 
 // DoUTFConversion ------------------------------------------------------------
@@ -171,7 +171,7 @@
   bool success = true;
 
   for (size_t i = 0; i < src_len; ++i) {
-    base_icu::UChar32 code_point = src[i];
+    auto code_point = static_cast<base_icu::UChar32>(src[i]);
 
     if (!IsValidCodepoint(code_point)) {
       success = false;
diff --git a/build/build_config.h b/build/build_config.h
index a993e1e..1914750 100644
--- a/build/build_config.h
+++ b/build/build_config.h
@@ -49,7 +49,7 @@
 #ifndef BUILD_BUILD_CONFIG_H_
 #define BUILD_BUILD_CONFIG_H_
 
-#include "build/buildflag.h"
+#include "build/buildflag.h"  // IWYU pragma: export
 
 // A set of macros to use for platform detection.
 #if defined(__native_client__)
diff --git a/url/url_constants.cc b/url/url_constants.cc
index 9685098..ee21a27 100644
--- a/url/url_constants.cc
+++ b/url/url_constants.cc
@@ -50,6 +50,8 @@
 const char16_t kUrnScheme16[] = u"urn";
 const char kUuidInPackageScheme[] = "uuid-in-package";
 const char16_t kUuidInPackageScheme16[] = u"uuid-in-package";
+const char kWebcalScheme[] = "webcal";
+const char16_t kWebcalScheme16[] = u"webcal";
 const char kWsScheme[] = "ws";
 const char16_t kWsScheme16[] = u"ws";
 const char kWssScheme[] = "wss";
diff --git a/url/url_constants.h b/url/url_constants.h
index b4a5889..9c72569 100644
--- a/url/url_constants.h
+++ b/url/url_constants.h
@@ -54,6 +54,8 @@
 COMPONENT_EXPORT(URL) extern const char16_t kUrnScheme16[];
 COMPONENT_EXPORT(URL) extern const char kUuidInPackageScheme[];
 COMPONENT_EXPORT(URL) extern const char16_t kUuidInPackageScheme16[];
+COMPONENT_EXPORT(URL) extern const char kWebcalScheme[];
+COMPONENT_EXPORT(URL) extern const char16_t kWebcalScheme16[];
 COMPONENT_EXPORT(URL) extern const char kWsScheme[];
 COMPONENT_EXPORT(URL) extern const char16_t kWsScheme16[];
 COMPONENT_EXPORT(URL) extern const char kWssScheme[];
diff --git a/url/url_util.cc b/url/url_util.cc
index a6d0901..ac6ffd7 100644
--- a/url/url_util.cc
+++ b/url/url_util.cc
@@ -29,6 +29,16 @@
   SchemeType type;
 };
 
+// A pair for representing a scheme and a custom protocol handler for it.
+//
+// This pair of strings must be normalized protocol handler parameters as
+// described in the Custom Handler specification.
+// https://html.spec.whatwg.org/multipage/system-state.html#normalize-protocol-handler-parameters
+struct SchemeWithHandler {
+  std::string scheme;
+  std::string handler;
+};
+
 // List of currently registered schemes and associated properties.
 struct SchemeRegistry {
   // Standard format schemes (see header for details).
@@ -101,6 +111,9 @@
       kAboutScheme,
   };
 
+  // Schemes with a predefined default custom handler.
+  std::vector<SchemeWithHandler> predefined_handler_schemes;
+
   bool allow_non_standard_schemes = false;
 };
 
@@ -501,6 +514,21 @@
       << "Trying to add a scheme after the lists have been locked.";
 }
 
+void DoAddSchemeWithHandler(const char* new_scheme,
+                            const char* handler,
+                            std::vector<SchemeWithHandler>* schemes) {
+  DoSchemeModificationPreamble();
+  GURL_DCHECK(schemes);
+  GURL_DCHECK(strlen(new_scheme) > 0);
+  GURL_DCHECK(strlen(handler) > 0);
+  GURL_DCHECK_EQ(gurl_base::ToLowerASCII(new_scheme), new_scheme);
+  GURL_DCHECK(std::find_if(schemes->begin(), schemes->end(),
+                      [&new_scheme](const SchemeWithHandler& scheme) {
+                        return scheme.scheme == new_scheme;
+                      }) == schemes->end());
+  schemes->push_back({new_scheme, handler});
+}
+
 void DoAddScheme(const char* new_scheme, std::vector<std::string>* schemes) {
   DoSchemeModificationPreamble();
   GURL_DCHECK(schemes);
@@ -649,6 +677,22 @@
   return GetSchemeRegistry().empty_document_schemes;
 }
 
+void AddPredefinedHandlerScheme(const char* new_scheme, const char* handler) {
+  DoAddSchemeWithHandler(
+      new_scheme, handler,
+      &GetSchemeRegistryWithoutLocking()->predefined_handler_schemes);
+}
+
+std::vector<std::pair<std::string, std::string>> GetPredefinedHandlerSchemes() {
+  std::vector<std::pair<std::string, std::string>> result;
+  result.reserve(GetSchemeRegistry().predefined_handler_schemes.size());
+  for (const SchemeWithHandler& entry :
+       GetSchemeRegistry().predefined_handler_schemes) {
+    result.emplace_back(entry.scheme, entry.handler);
+  }
+  return result;
+}
+
 void LockSchemeRegistries() {
   scheme_registries_locked = true;
 }
diff --git a/url/url_util.h b/url/url_util.h
index 00399c2..e622130 100644
--- a/url/url_util.h
+++ b/url/url_util.h
@@ -115,6 +115,16 @@
 COMPONENT_EXPORT(URL) void AddEmptyDocumentScheme(const char* new_scheme);
 COMPONENT_EXPORT(URL) const std::vector<std::string>& GetEmptyDocumentSchemes();
 
+// Adds a scheme with a predefined default handler.
+//
+// This pair of strings must be normalized protocol handler parameters as
+// described in the Custom Handler specification.
+// https://html.spec.whatwg.org/multipage/system-state.html#normalize-protocol-handler-parameters
+COMPONENT_EXPORT(URL)
+void AddPredefinedHandlerScheme(const char* new_scheme, const char* handler);
+COMPONENT_EXPORT(URL)
+std::vector<std::pair<std::string, std::string>> GetPredefinedHandlerSchemes();
+
 // Sets a flag to prevent future calls to Add*Scheme from succeeding.
 //
 // This is designed to help prevent errors for multithreaded applications.