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.