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.