Update googleurl to 9cf3e054c83f943c3bf8a87e6f75cab19b3e08c1 The upstream Chromium revision is of Fri Apr 29 00:14:16 2022 +0000 Change-Id: I91e2af9b25b0489738b8a0126630abae1c06fda2
diff --git a/AUTHORS b/AUTHORS index 364df55..5941416 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -47,7 +47,9 @@ Alec Petridis <alecthechop@gmail.com> Aleksandar Stojiljkovic <aleksandar.stojiljkovic@intel.com> Aleksei Gurianov <gurianov@gmail.com> +Aleksey Khoroshilov <akhoroshilov@brave.com> Alesandro Ortiz <alesandro@alesandroortiz.com> +Alessandro Astone <ales.astone@gmail.com> Alex Chronopoulos <achronop@gmail.com> Alex Gabriel <minilogo@gmail.com> Alex Gartrell <agartrell@cmu.edu> @@ -90,6 +92,7 @@ Ancil George <ancilgeorge@samsung.com> Andra Paraschiv <andra.paraschiv@intel.com> Andras Tokodi <a.tokodi@eyeo.com> +Andreas Nazlidis <andreas221b@gmail.com> Andreas Papacharalampous <andreas@apap04.com> Andrei Borza <andrei.borza@gmail.com> Andrei Parvu <andrei.prv@gmail.com> @@ -113,11 +116,13 @@ Anshul Jain <anshul.jain@samsung.com> Anssi Hannula <anssi.hannula@iki.fi> Anthony Halliday <anth.halliday12@gmail.com> -Anton Bershanskiy <bershanskiy@pm.me> +Anton Bershanskiy <8knots@protonmail.com> Anton Obzhirov <a.obzhirov@samsung.com> Antonin Hildebrand <antonin.hildebrand@gmail.com> Antonio Gomes <a1.gomes@sisa.samsung.com> Anuj Kumar Sharma <anujk.sharma@samsung.com> +Ao Sun <ntusunao@gmail.com> +Ao Wang <wangao.james@bytedance.com> Arjun Karthik <arjunkar@amazon.com> Arman Ghotb <armanghotb@gmail.com> Armin Burgmeier <aburgmeier@bloomberg.net> @@ -167,6 +172,7 @@ Brendan Long <self@brendanlong.com> Brendon Tiszka <btiszka@gmail.com> Brian Clifton <clifton@brave.com> +Brian Dunn <brian@theophil.us> Brian G. Merrell <bgmerrell@gmail.com> Brian Konzman, SJ <b.g.konzman@gmail.com> Brian Luft <brian@electroly.com> @@ -245,6 +251,7 @@ Daniel Carvalho Liedke <dliedke@gmail.com> Daniel Charles <daniel.charles@intel.com> Daniel Imms <daniimms@amazon.com> +Daniel Izquierdo <daniel.izquierdo@gmail.com> Daniel Johnson <danielj41@gmail.com> Daniel Lockyer <thisisdaniellockyer@gmail.com> Daniel Nishi <dhnishi@gmail.com> @@ -346,6 +353,7 @@ Evgeny Agafonchikov <evgeny.agafonchikov@akvelon.com> Fabian Henneke <fabian.henneke@gmail.com> Fabien Tassin <fta@sofaraway.org> +Feifei Wang <alexswang@tencent.com> Felipe Erias Morandeira <felipeerias@gmail.com> Felix H. Dahlke <fhd@ubercode.de> Felix Weilbach <feweilbach@gmail.com> @@ -413,6 +421,7 @@ Hautio Kari <khautio@gmail.com> Heejin R. Chung <heejin.r.chung@samsung.com> Heeyoun Lee <heeyoun.lee@samsung.com> +Henrique de Carvalho <decarv.henrique@gmail.com> Henrique Limas <henrique.ramos.limas@gmail.com> Himanshu Joshi <h.joshi@samsung.com> Hiroyuki Matsuda <gsittyz@gmail.com> @@ -572,6 +581,7 @@ Joone Hur <joone.hur@intel.com> Joonghun Park <pjh0718@gmail.com> Jorge Villatoro <jorge@tomatocannon.com> +Jorrit Jongma <jorrit@jongma.org> Joseph Gentle <josephg@gmail.com> Joseph Lolak <joseph.lolak@samsung.com> Josh Triplett <josh.triplett@intel.com> @@ -599,6 +609,7 @@ Jungkee Song <jungkee.song@samsung.com> Junmin Zhu <junmin.zhu@intel.com> Junsong Li <ljs.darkfish@gmail.com> +Jun Wang <wangjuna@uniontech.com> Jun Zeng <hjunzeng6@gmail.com> Justin Okamoto <justmoto@amazon.com> Justin Ribeiro <justin@justinribeiro.com> @@ -708,6 +719,7 @@ Luke Zarko <lukezarko@gmail.com> Luoxi Pan <l.panpax@gmail.com> Lu Yahan <yahan@iscas.ac.cn> +Ma Aiguo <maaiguo@uniontech.com> Maarten Lankhorst <m.b.lankhorst@gmail.com> Maciej Pawlowski <m.pawlowski@eyeo.com> Magnus Danielsson <fuzzac@gmail.com> @@ -813,6 +825,7 @@ Mohammed Wajahat Ali Siddiqui <wajahat.s@samsung.com> Mohan Reddy <mohan.reddy@samsung.com> Mohit Bhalla <bhallam@amazon.com> +Moiseanu Rares-Marian <moiseanurares@gmail.com> Momoka Yamamoto <momoka.my6@gmail.com> Momoko Hattori <momohatt10@gmail.com> Mostafa Sedaghat joo <mostafa.sedaghat@gmail.com> @@ -880,6 +893,7 @@ Pavel Ivanov <paivanof@gmail.com> Pawel Forysiuk <p.forysiuk@samsung.com> PaweÅ‚ Hajdan jr <phajdan.jr@gmail.com> +PaweÅ‚ Stanek <pawel@gener8ads.com> Piotr Zarycki <piotr.zarycki@gmail.com> Payal Pandey <payal.pandey@samsung.com> Pedro Tôrres <t0rr3s.p3dr0@gmail.com> @@ -887,6 +901,7 @@ Peng Jiang <leiyi.jp@gmail.com> Peng Xinchao <pxinchao@gmail.com> Peng-Yu Chen <pengyu@libstarrify.so> +Pei Wang <wangpei@uniontech.com> Peter Bright <drpizza@quiscalusmexicanus.org> Peter Brophy <pbrophy@adobe.com> Peter Collingbourne <peter@pcc.me.uk> @@ -942,6 +957,7 @@ Ravi Phaneendra Kasibhatla <r.kasibhatla@samsung.com> Ravi Phaneendra Kasibhatla <ravi.kasibhatla@motorola.com> Raviraj Sitaram <raviraj.p.sitaram@intel.com> +Rebecca Chang Swee Fun <rebecca.chang@starfivetech.com> Reda Tawfik <redatawfik@noogler.google.com> Réda Housni Alaoui <alaoui.rda@gmail.com> Refael Ackermann <refack@gmail.com> @@ -995,6 +1011,7 @@ Samuel Attard <samuel.r.attard@gmail.com> Sanggi Hong <sanggi.hong11@gmail.com> Sanghee Lee <sanghee.lee1992@gmail.com> +Sangheon Kim <sangheon77.kim@samsung.com> Sanghyun Park <sh919.park@samsung.com> Sanghyup Lee <sh53.lee@samsung.com> Sangjoon Je <htamop@gmail.com> @@ -1041,6 +1058,7 @@ ShankarGanesh K <blr.bmlab@gmail.com> Shanmuga Pandi M <shanmuga.m@samsung.com> Shaobo Yan <shaobo.yan@intel.com> +Shaotang Zhu <zhushaotang@uniontech.com> Shashi Kumar <sk.kumar@samsung.com> Shawn Anastasio <shawnanastasio@gmail.com> Shelley Vohr <shelley.vohr@gmail.com> @@ -1064,6 +1082,7 @@ Shubham Agrawal <shubag@amazon.com> Shubham Gupta <shubh.gupta@samsung.com> Siba Samal <siba.samal@samsung.com> +Sida Zhu <zhusida@bytedance.com> Siddharth Bagai <b.siddharth@samsung.com> Siddharth Shankar <funkysidd@gmail.com> Simeon Kuran <simeon.kuran@gmail.com> @@ -1151,6 +1170,7 @@ Tibor Dusnoki <tdusnoki@inf.u-szeged.hu> Tim Ansell <mithro@mithis.com> Tim Niederhausen <tim@rnc-ag.de> +Tim Steiner <twsteiner@gmail.com> Timo Gurr <timo.gurr@gmail.com> Timo Reimann <ttr314@googlemail.com> Timo Witte <timo.witte@gmail.com> @@ -1200,6 +1220,7 @@ Waihung Fu <fufranci@amazon.com> wafuwafu13 <mariobaske@i.softbank.jp> Wojciech Bielawski <wojciech.bielawski@gmail.com> +Wang Weiwei <wangww@dingdao.com> Wanming Lin <wanming.lin@intel.com> Wei Li <wei.c.li@intel.com> Wen Fan <fanwen1@huawei.com> @@ -1214,6 +1235,7 @@ Will Watts <willwatts.ww@googlemail.com> William Xie <william.xie@intel.com> Winston Chen <winston.c1@samsung.com> +Xialei Qin <qinxialei@uniontech.com> Xiang Long <xiang.long@intel.com> XiangYang <yangxiang12@huawei.com> Xiangze Zhang <xiangze.zhang@intel.com> @@ -1223,6 +1245,7 @@ Xiaoshu Zhang <xiaoshu@amazon.com> Xiaoyin Liu <xiaoyin.l@outlook.com> Xinchao He <hexinchao@gmail.com> +Xinchao Tian <tianxinchao@360.cn> Xing Zhang <xzhang@adobe.com> Xinghua Cao <xinghua.cao@intel.com> Xu Samuel <samuel.xu@intel.com> @@ -1236,6 +1259,7 @@ Yael Aharon <yael.aharon@intel.com> Yan Wang <yan0422.wang@samsung.com> Yang Gu <yang.gu@intel.com> +Yang Liu <jd9668954@gmail.com> Yannic Bonenberger <yannic.bonenberger@gmail.com> Yarin Kaul <yarin.kaul@gmail.com> Yash Vempati <vempatiy@amazon.com> @@ -1250,6 +1274,7 @@ Yizhou Jiang <yizhou.jiang@intel.com> Yoav Weiss <yoav@yoav.ws> Yoav Zilberberg <yoav.zilberberg@gmail.com> +Yong Ling <yongling@tencent.com> Yong Shin <sy3620@gmail.com> Yong Wang <ccyongwang@tencent.com> Yongha Lee <yongha78.lee@samsung.com> @@ -1321,6 +1346,7 @@ CoSMo Software pvt ltd <*@cosmosoftware.io> Cosium <*@cosium.com> Dell Technologies Inc. <*@dell.corp-partner.google.com> +Ding (Beijing) Intelligent Technology Co. Ltd <*@dingdao.com> Duck Duck Go, Inc. <*@duckduckgo.com> Endless Mobile, Inc. <*@endlessm.com> EngFlow, Inc. <*@engflow.com>
diff --git a/base/BUILD b/base/BUILD index 9de3117..c77528b 100644 --- a/base/BUILD +++ b/base/BUILD
@@ -38,7 +38,6 @@ "ranges/ranges.h", "stl_util.h", "template_util.h", - "strings/char_traits.h", "strings/string_piece_forward.h", "strings/string_piece.h", "strings/string_util.h",
diff --git a/base/containers/contains.h b/base/containers/contains.h index 55b1fb5..559ff2c 100644 --- a/base/containers/contains.h +++ b/base/containers/contains.h
@@ -10,7 +10,6 @@ #include "base/ranges/algorithm.h" #include "base/ranges/ranges.h" -#include "base/template_util.h" namespace gurl_base { @@ -22,7 +21,7 @@ struct HasKeyType : std::false_type {}; template <typename T> -struct HasKeyType<T, void_t<typename T::key_type>> : std::true_type {}; +struct HasKeyType<T, std::void_t<typename T::key_type>> : std::true_type {}; // Probe whether a `contains` member function exists and return the result of // `container.contains(value)` if this is a valid expression. This is the
diff --git a/base/containers/contiguous_iterator.h b/base/containers/contiguous_iterator.h index ca8e7b3..f17a8ed 100644 --- a/base/containers/contiguous_iterator.h +++ b/base/containers/contiguous_iterator.h
@@ -12,7 +12,6 @@ #include <vector> #include "base/containers/checked_iterators.h" -#include "base/template_util.h" namespace gurl_base { @@ -28,8 +27,8 @@ template <typename T, typename StringT = std::basic_string<iter_value_t<T>>> struct IsStringIterImpl - : disjunction<std::is_same<T, typename StringT::const_iterator>, - std::is_same<T, typename StringT::iterator>> {}; + : std::disjunction<std::is_same<T, typename StringT::const_iterator>, + std::is_same<T, typename StringT::iterator>> {}; // An iterator to std::basic_string is contiguous. // Reference: https://wg21.link/basic.string.general#2 @@ -38,22 +37,24 @@ // `static_assert(is_trivial_v<value_type>)` inside libc++'s std::basic_string. template <typename T> struct IsStringIter - : conjunction<std::is_trivial<iter_value_t<T>>, IsStringIterImpl<T>> {}; + : std::conjunction<std::is_trivial<iter_value_t<T>>, IsStringIterImpl<T>> { +}; // An iterator to std::array is contiguous. // Reference: https://wg21.link/array.overview#1 template <typename T, typename ArrayT = std::array<iter_value_t<T>, 1>> struct IsArrayIter - : disjunction<std::is_same<T, typename ArrayT::const_iterator>, - std::is_same<T, typename ArrayT::iterator>> {}; + : std::disjunction<std::is_same<T, typename ArrayT::const_iterator>, + std::is_same<T, typename ArrayT::iterator>> {}; // An iterator to a non-bool std::vector is contiguous. // Reference: https://wg21.link/vector.overview#2 template <typename T, typename VectorT = std::vector<iter_value_t<T>>> struct IsVectorIter - : conjunction<negation<std::is_same<iter_value_t<T>, bool>>, - disjunction<std::is_same<T, typename VectorT::const_iterator>, - std::is_same<T, typename VectorT::iterator>>> {}; + : std::conjunction< + std::negation<std::is_same<iter_value_t<T>, bool>>, + std::disjunction<std::is_same<T, typename VectorT::const_iterator>, + std::is_same<T, typename VectorT::iterator>>> {}; // The result of passing a std::valarray to std::begin is a contiguous iterator. // Note: Since all common standard library implementations (i.e. libc++, @@ -67,20 +68,21 @@ // base's CheckedContiguousIterator is a contiguous iterator. template <typename T, typename ValueT = iter_value_t<T>> struct IsCheckedContiguousIter - : disjunction<std::is_same<T, gurl_base::CheckedContiguousConstIterator<ValueT>>, - std::is_same<T, gurl_base::CheckedContiguousIterator<ValueT>>> {}; + : std::disjunction< + std::is_same<T, gurl_base::CheckedContiguousConstIterator<ValueT>>, + std::is_same<T, gurl_base::CheckedContiguousIterator<ValueT>>> {}; // Check that the iterator points to an actual object, and is one of the // iterator types mentioned above. template <typename T> struct IsContiguousIteratorImpl - : conjunction<PointsToObject<T>, - disjunction<IsPointer<T>, - IsStringIter<T>, - IsArrayIter<T>, - IsVectorIter<T>, - IsValueArrayIter<T>, - IsCheckedContiguousIter<T>>> {}; + : std::conjunction<PointsToObject<T>, + std::disjunction<IsPointer<T>, + IsStringIter<T>, + IsArrayIter<T>, + IsVectorIter<T>, + IsValueArrayIter<T>, + IsCheckedContiguousIter<T>>> {}; } // namespace internal
diff --git a/base/containers/span.h b/base/containers/span.h index 1ba60b1..c0fb0b6 100644 --- a/base/containers/span.h +++ b/base/containers/span.h
@@ -14,13 +14,11 @@ #include <type_traits> #include <utility> -#include "polyfills/base/check_op.h" +#include "polyfills/base/check.h" #include "base/compiler_specific.h" #include "base/containers/checked_iterators.h" #include "base/containers/contiguous_iterator.h" -#include "base/cxx17_backports.h" #include "base/cxx20_to_address.h" -#include "base/template_util.h" namespace gurl_base { @@ -57,7 +55,7 @@ struct IsSpanImpl<span<T, Extent>> : std::true_type {}; template <typename T> -using IsNotSpan = negation<IsSpanImpl<std::decay_t<T>>>; +using IsNotSpan = std::negation<IsSpanImpl<std::decay_t<T>>>; template <typename T> struct IsStdArrayImpl : std::false_type {}; @@ -66,10 +64,10 @@ struct IsStdArrayImpl<std::array<T, N>> : std::true_type {}; template <typename T> -using IsNotStdArray = negation<IsStdArrayImpl<std::decay_t<T>>>; +using IsNotStdArray = std::negation<IsStdArrayImpl<std::decay_t<T>>>; template <typename T> -using IsNotCArray = negation<std::is_array<std::remove_reference_t<T>>>; +using IsNotCArray = std::negation<std::is_array<std::remove_reference_t<T>>>; template <typename From, typename To> using IsLegalDataConversion = std::is_convertible<From (*)[], To (*)[]>; @@ -80,17 +78,17 @@ template <typename Iter, typename T> using EnableIfCompatibleContiguousIterator = std::enable_if_t< - conjunction<IsContiguousIterator<Iter>, - IteratorHasConvertibleReferenceType<Iter, T>>::value>; + std::conjunction<IsContiguousIterator<Iter>, + IteratorHasConvertibleReferenceType<Iter, T>>::value>; template <typename Container, typename T> using ContainerHasConvertibleData = IsLegalDataConversion< - std::remove_pointer_t<decltype(gurl_base::data(std::declval<Container>()))>, + std::remove_pointer_t<decltype(std::data(std::declval<Container>()))>, T>; template <typename Container> using ContainerHasIntegralSize = - std::is_integral<decltype(gurl_base::size(std::declval<Container>()))>; + std::is_integral<decltype(std::size(std::declval<Container>()))>; template <typename From, size_t FromExtent, typename To, size_t ToExtent> using EnableIfLegalSpanConversion = @@ -107,11 +105,11 @@ // SFINAE check if Container can be converted to a span<T>. template <typename Container, typename T> using IsSpanCompatibleContainer = - conjunction<IsNotSpan<Container>, - IsNotStdArray<Container>, - IsNotCArray<Container>, - ContainerHasConvertibleData<Container, T>, - ContainerHasIntegralSize<Container>>; + std::conjunction<IsNotSpan<Container>, + IsNotStdArray<Container>, + IsNotCArray<Container>, + ContainerHasConvertibleData<Container, T>, + ContainerHasIntegralSize<Container>>; template <typename Container, typename T> using EnableIfSpanCompatibleContainer = @@ -297,7 +295,7 @@ template < size_t N, typename = internal::EnableIfSpanCompatibleArray<T (&)[N], T, Extent>> - constexpr span(T (&array)[N]) noexcept : span(gurl_base::data(array), N) {} + constexpr span(T (&array)[N]) noexcept : span(std::data(array), N) {} template < typename U, @@ -305,17 +303,17 @@ typename = internal::EnableIfSpanCompatibleArray<std::array<U, N>&, T, Extent>> constexpr span(std::array<U, N>& array) noexcept - : span(gurl_base::data(array), N) {} + : span(std::data(array), N) {} template <typename U, size_t N, typename = internal:: EnableIfSpanCompatibleArray<const std::array<U, N>&, T, Extent>> constexpr span(const std::array<U, N>& array) noexcept - : span(gurl_base::data(array), N) {} + : span(std::data(array), N) {} - // Conversion from a container that has compatible gurl_base::data() and integral - // gurl_base::size(). + // Conversion from a container that has compatible std::data() and integral + // std::size(). template < typename Container, typename = @@ -323,7 +321,7 @@ T, Extent>> constexpr span(Container& container) noexcept - : span(gurl_base::data(container), gurl_base::size(container)) {} + : span(std::data(container), std::size(container)) {} template < typename Container, @@ -332,7 +330,7 @@ T, Extent>> constexpr span(const Container& container) noexcept - : span(gurl_base::data(container), gurl_base::size(container)) {} + : span(std::data(container), std::size(container)) {} constexpr span(const span& other) noexcept = default; @@ -485,7 +483,7 @@ template <int&... ExplicitArgumentBarrier, typename Container> constexpr auto make_span(Container&& container) noexcept { using T = - std::remove_pointer_t<decltype(gurl_base::data(std::declval<Container>()))>; + std::remove_pointer_t<decltype(std::data(std::declval<Container>()))>; using Extent = internal::Extent<Container>; return span<T, Extent::value>(std::forward<Container>(container)); } @@ -510,8 +508,8 @@ template <size_t N, int&... ExplicitArgumentBarrier, typename Container> constexpr auto make_span(Container&& container) noexcept { using T = - std::remove_pointer_t<decltype(gurl_base::data(std::declval<Container>()))>; - return span<T, N>(gurl_base::data(container), gurl_base::size(container)); + std::remove_pointer_t<decltype(std::data(std::declval<Container>()))>; + return span<T, N>(std::data(container), std::size(container)); } } // namespace base @@ -520,7 +518,7 @@ // with definite extent, i.e. everything that is a contiguous storage of some // sort with static size. Specifically, this works for std::array in a constexpr // context. Note: -// * |gurl_base::size| should be preferred for plain arrays. +// * |std::size| should be preferred for plain arrays. // * In run-time contexts, functions such as |std::array::size| should be // preferred. #define EXTENT(x) \
diff --git a/base/cxx17_backports.h b/base/cxx17_backports.h index 81e573f..86976d4 100644 --- a/base/cxx17_backports.h +++ b/base/cxx17_backports.h
@@ -5,11 +5,7 @@ #ifndef BASE_CXX17_BACKPORTS_H_ #define BASE_CXX17_BACKPORTS_H_ -#include <array> #include <functional> -#include <initializer_list> -#include <memory> -#include <string> #include <tuple> #include <type_traits> #include <utility> @@ -19,83 +15,6 @@ namespace gurl_base { -// C++14 implementation of C++17's std::size(): -// http://en.cppreference.com/w/cpp/iterator/size -template <typename Container> -constexpr auto size(const Container& c) -> decltype(c.size()) { - return c.size(); -} - -template <typename T, size_t N> -constexpr size_t size(const T (&array)[N]) noexcept { - return N; -} - -// C++14 implementation of C++17's std::empty(): -// http://en.cppreference.com/w/cpp/iterator/empty -template <typename Container> -constexpr auto empty(const Container& c) -> decltype(c.empty()) { - return c.empty(); -} - -template <typename T, size_t N> -constexpr bool empty(const T (&array)[N]) noexcept { - return false; -} - -template <typename T> -constexpr bool empty(std::initializer_list<T> il) noexcept { - return il.size() == 0; -} - -// C++14 implementation of C++17's std::data(): -// http://en.cppreference.com/w/cpp/iterator/data -template <typename Container> -constexpr auto data(Container& c) -> decltype(c.data()) { - return c.data(); -} - -// std::basic_string::data() had no mutable overload prior to C++17 [1]. -// Hence this overload is provided. -// Note: str[0] is safe even for empty strings, as they are guaranteed to be -// null-terminated [2]. -// -// [1] http://en.cppreference.com/w/cpp/string/basic_string/data -// [2] http://en.cppreference.com/w/cpp/string/basic_string/operator_at -template <typename CharT, typename Traits, typename Allocator> -CharT* data(std::basic_string<CharT, Traits, Allocator>& str) { - return std::addressof(str[0]); -} - -template <typename Container> -constexpr auto data(const Container& c) -> decltype(c.data()) { - return c.data(); -} - -template <typename T, size_t N> -constexpr T* data(T (&array)[N]) noexcept { - return array; -} - -template <typename T> -constexpr const T* data(std::initializer_list<T> il) noexcept { - return il.begin(); -} - -// std::array::data() was not constexpr prior to C++17 [1]. -// Hence these overloads are provided. -// -// [1] https://en.cppreference.com/w/cpp/container/array/data -template <typename T, size_t N> -constexpr T* data(std::array<T, N>& array) noexcept { - return !array.empty() ? &array[0] : nullptr; -} - -template <typename T, size_t N> -constexpr const T* data(const std::array<T, N>& array) noexcept { - return !array.empty() ? &array[0] : nullptr; -} - // C++14 implementation of C++17's std::clamp(): // https://en.cppreference.com/w/cpp/algorithm/clamp // Please note that the C++ spec makes it undefined behavior to call std::clamp
diff --git a/base/debug/crash_logging.cc b/base/debug/crash_logging.cc index f6bad4f..a6e3719 100644 --- a/base/debug/crash_logging.cc +++ b/base/debug/crash_logging.cc
@@ -35,7 +35,7 @@ g_crash_key_impl->Clear(crash_key); } -BASE_EXPORT void OutputCrashKeysToStream(std::ostream& out) { +void OutputCrashKeysToStream(std::ostream& out) { if (!g_crash_key_impl) return;
diff --git a/base/debug/crash_logging.h b/base/debug/crash_logging.h index fdc5343..98f40c1 100644 --- a/base/debug/crash_logging.h +++ b/base/debug/crash_logging.h
@@ -12,7 +12,6 @@ #include <type_traits> #include "polyfills/base/base_export.h" -#include "base/cxx17_backports.h" #include "base/memory/raw_ptr.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" @@ -125,7 +124,7 @@ // that restricts the name of a crash key to 40 characters. #define SCOPED_CRASH_KEY_STRING_INTERNAL2(category, name, nonce, data, \ key_size) \ - static_assert(::gurl_base::size(category "-" name) < 40, \ + static_assert(::std::size(category "-" name) < 40, \ "Crash key names must be shorter than 40 characters."); \ ::gurl_base::debug::ScopedCrashKeyString scoped_crash_key_helper##nonce( \ [] { \
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h index 16094d3..ad53dc5 100644 --- a/base/memory/raw_ptr.h +++ b/base/memory/raw_ptr.h
@@ -14,29 +14,44 @@ #include <utility> #include "polyfills/base/allocator/buildflags.h" + #include "polyfills/base/check.h" #include "base/compiler_specific.h" #include "polyfills/base/dcheck_is_on.h" +#include "polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h" #include "build/build_config.h" #include "build/buildflag.h" -#if BUILDFLAG(USE_BACKUP_REF_PTR) +#if BUILDFLAG(USE_BACKUP_REF_PTR) || \ + defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) // USE_BACKUP_REF_PTR implies USE_PARTITION_ALLOC, needed for code under // allocator/partition_allocator/ to be built. #include "base/allocator/partition_allocator/address_pool_manager_bitmap.h" #include "base/allocator/partition_allocator/partition_address_space.h" -#include "base/allocator/partition_allocator/partition_alloc_config.h" #include "base/allocator/partition_allocator/partition_alloc_constants.h" #include "polyfills/base/base_export.h" -#endif // BUILDFLAG(USE_BACKUP_REF_PTR) +#endif // BUILDFLAG(USE_BACKUP_REF_PTR) || + // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) + +#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) +#include "base/allocator/partition_allocator/partition_tag.h" +#include "base/allocator/partition_allocator/tagging.h" +#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) #if BUILDFLAG(IS_WIN) #include <windows.h> #endif +#if defined(OFFICIAL_BUILD) +// The annotation changed compiler output and increased binary size so disable +// for official builds. +// TODO(crbug.com/1320670): Remove when issue is resolved. +#define RAW_PTR_EXCLUSION +#else // Marks a field as excluded from the raw_ptr usage enforcement clang plugin. // Example: RAW_PTR_EXCLUSION Foo* foo_; #define RAW_PTR_EXCLUSION __attribute__((annotate("raw_ptr_exclusion"))) +#endif namespace cc { class Scheduler; @@ -50,13 +65,8 @@ namespace gurl_base { -// NOTE: All methods should be `ALWAYS_INLINE NO_STACK_PROTECTOR`. -// ALWAYS_INLINE: raw_ptr is meant to be a lightweight replacement of a raw -// pointer, hence performance is critical. -// NO_STACK_PROTECTOR: This annotation is required to avoid failures when a -// raw_ptr is inside a NO_STACK_PROTECTOR function. -// TODO(https://crbug.com/1274129): Remove NO_STACK_PROTECTOR. -#define RAW_PTR_FUNC_ATTRIBUTES ALWAYS_INLINE NO_STACK_PROTECTOR +// NOTE: All methods should be `ALWAYS_INLINE`. raw_ptr is meant to be a +// lightweight replacement of a raw pointer, hence performance is critical. namespace internal { // These classes/structures are part of the raw_ptr implementation. @@ -65,41 +75,38 @@ struct RawPtrNoOpImpl { // Wraps a pointer. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* WrapRawPtr(T* ptr) { + static ALWAYS_INLINE T* WrapRawPtr(T* ptr) { return ptr; } // Notifies the allocator when a wrapped pointer is being removed or replaced. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES void ReleaseWrappedPtr(T*) {} + static ALWAYS_INLINE void ReleaseWrappedPtr(T*) {} // Unwraps the pointer, while asserting that memory hasn't been freed. The // function is allowed to crash on nullptr. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForDereference( - T* wrapped_ptr) { + static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) { return wrapped_ptr; } // Unwraps the pointer, while asserting that memory hasn't been freed. The // function must handle nullptr gracefully. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForExtraction( - T* wrapped_ptr) { + static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) { return wrapped_ptr; } // Unwraps the pointer, without making an assertion on whether memory was // freed or not. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* UnsafelyUnwrapPtrForComparison( - T* wrapped_ptr) { + static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) { return wrapped_ptr; } // Upcasts the wrapped pointer. template <typename To, typename From> - static RAW_PTR_FUNC_ATTRIBUTES constexpr To* Upcast(From* wrapped_ptr) { + static ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) { static_assert(std::is_convertible<From*, To*>::value, "From must be convertible to To."); // Note, this cast may change the address if upcasting to base that lies in @@ -109,24 +116,180 @@ // Advance the wrapped pointer by |delta| bytes. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* Advance(T* wrapped_ptr, - ptrdiff_t delta_elems) { + static ALWAYS_INLINE T* Advance(T* wrapped_ptr, ptrdiff_t delta_elems) { return wrapped_ptr + delta_elems; } // Returns a copy of a wrapped pointer, without making an assertion on whether // memory was freed or not. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* Duplicate(T* wrapped_ptr) { + static ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) { return wrapped_ptr; } // This is for accounting only, used by unit tests. - static RAW_PTR_FUNC_ATTRIBUTES void IncrementSwapCountForTest() {} - static RAW_PTR_FUNC_ATTRIBUTES void - IncrementPointerToMemberOperatorCountForTest() {} + static ALWAYS_INLINE void IncrementSwapCountForTest() {} + static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {} }; +#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) + +constexpr int kValidAddressBits = 48; +constexpr uintptr_t kAddressMask = (1ull << kValidAddressBits) - 1; +constexpr int kTagBits = sizeof(uintptr_t) * 8 - kValidAddressBits; + +// 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; + +constexpr int kTopBitShift = 63; +constexpr uintptr_t kTopBit = 1ull << kTopBitShift; +static_assert(kTopBit << 1 == 0, "kTopBit should really be the top bit"); +static_assert((kTopBit & kTagMask) > 0, + "kTopBit bit must be inside the tag region"); + +// This functionality is outside of MTECheckedPtrImpl, so that it can be +// overridden by tests. +struct MTECheckedPtrImplPartitionAllocSupport { + // 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)); + // MTECheckedPtr algorithms work only when memory is + // allocated by PartitionAlloc, from normal buckets pool. + // + // TODO(crbug.com/1307514): Allow direct-map buckets. + return IsManagedByPartitionAlloc(as_uintptr) && + IsManagedByNormalBuckets(as_uintptr); + } + + // Returns pointer to the tag that protects are pointed by |ptr|. + static ALWAYS_INLINE void* TagPointer(uintptr_t ptr) { + return partition_alloc::PartitionTagPointer(ptr); + } +}; + +template <typename PartitionAllocSupport> +struct MTECheckedPtrImpl { + // This implementation assumes that pointers are 64 bits long and at least 16 + // top bits are unused. The latter is harder to verify statically, but this is + // true for all currently supported 64-bit architectures (GURL_DCHECK when wrapping + // will verify that). + static_assert(sizeof(void*) >= 8, "Need 64-bit pointers"); + + // 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); + 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); + } + + // Read the tag and place it in the top bits of the address. + // Even if PartitionAlloc's tag has less than kTagBits, we'll read + // what's given and pad the rest with 0s. + static_assert(sizeof(partition_alloc::PartitionTag) * 8 <= kTagBits, ""); + uintptr_t tag = *(static_cast<volatile partition_alloc::PartitionTag*>( + PartitionAllocSupport::TagPointer(addr))); + + tag <<= kValidAddressBits; + addr |= tag; + return reinterpret_cast<T*>(addr); + } + + // Notifies the allocator when a wrapped pointer is being removed or replaced. + // No-op for MTECheckedPtrImpl. + template <typename T> + static ALWAYS_INLINE void ReleaseWrappedPtr(T*) {} + + // Unwraps the pointer's uintptr_t representation, while asserting that memory + // 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); + uintptr_t tag = ExtractTag(wrapped_addr); + if (tag > 0) { + // Read the tag provided by PartitionAlloc. + // + // Cast to volatile to ensure memory is read. E.g. in a tight loop, the + // compiler could cache the value in a register and thus could miss that + // another thread freed memory and changed tag. + uintptr_t read_tag = + *static_cast<volatile partition_alloc::PartitionTag*>( + PartitionAllocSupport::TagPointer(ExtractAddress(wrapped_addr))); + if (UNLIKELY(tag != read_tag)) + IMMEDIATE_CRASH(); + return reinterpret_cast<T*>(ExtractAddress(wrapped_addr)); + } + return wrapped_ptr; + } + + // Unwraps the pointer's uintptr_t representation, while asserting that memory + // hasn't been freed. The function must handle nullptr gracefully. + template <typename T> + static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) { + // SafelyUnwrapPtrForDereference handles nullptr case well. + return SafelyUnwrapPtrForDereference(wrapped_ptr); + } + + // Unwraps the pointer's uintptr_t representation, without making an assertion + // on whether memory was freed or not. + template <typename T> + static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) { + return ExtractPtr(wrapped_ptr); + } + + // Upcasts the wrapped pointer. + template <typename To, typename From> + static ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) { + static_assert(std::is_convertible<From*, To*>::value, + "From must be convertible to To."); + + // The top-bit tag must not affect the result of upcast. + return static_cast<To*>(wrapped_ptr); + } + + // Advance the wrapped pointer by |delta| bytes. + template <typename T> + static ALWAYS_INLINE T* Advance(T* wrapped_ptr, ptrdiff_t delta_elem) { + return wrapped_ptr + delta_elem; + } + + // Returns a copy of a wrapped pointer, without making an assertion + // on whether memory was freed or not. + template <typename T> + static ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) { + return wrapped_ptr; + } + + // This is for accounting only, used by unit tests. + static ALWAYS_INLINE void IncrementSwapCountForTest() {} + static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {} + + private: + static ALWAYS_INLINE uintptr_t ExtractAddress(uintptr_t wrapped_ptr) { + return wrapped_ptr & kAddressMask; + } + + template <typename T> + static ALWAYS_INLINE T* ExtractPtr(T* wrapped_ptr) { + return reinterpret_cast<T*>( + ExtractAddress(reinterpret_cast<uintptr_t>(wrapped_ptr))); + } + + static ALWAYS_INLINE uintptr_t ExtractTag(uintptr_t wrapped_ptr) { + return (wrapped_ptr & kTagMask) >> kValidAddressBits; + } +}; + +#endif // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) + #if BUILDFLAG(USE_BACKUP_REF_PTR) #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) @@ -134,12 +297,13 @@ uintptr_t address); #endif +template <bool AllowDangling = false> struct BackupRefPtrImpl { // Note that `BackupRefPtrImpl` itself is not thread-safe. If multiple threads // modify the same smart pointer object without synchronization, a data race // will occur. - static RAW_PTR_FUNC_ATTRIBUTES bool IsSupportedAndNotNull(uintptr_t address) { + static ALWAYS_INLINE bool IsSupportedAndNotNull(uintptr_t address) { // This covers the nullptr case, as address 0 is never in GigaCage. bool is_in_brp_pool = IsManagedByPartitionAllocBRPPool(address); @@ -192,7 +356,7 @@ // Wraps a pointer. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* WrapRawPtr(T* ptr) { + static ALWAYS_INLINE T* WrapRawPtr(T* ptr) { uintptr_t address = reinterpret_cast<uintptr_t>(ptr); if (IsSupportedAndNotNull(address)) { #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) @@ -211,7 +375,7 @@ // Notifies the allocator when a wrapped pointer is being removed or replaced. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES void ReleaseWrappedPtr(T* wrapped_ptr) { + static ALWAYS_INLINE void ReleaseWrappedPtr(T* wrapped_ptr) { uintptr_t address = reinterpret_cast<uintptr_t>(wrapped_ptr); if (IsSupportedAndNotNull(address)) { #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) @@ -231,8 +395,7 @@ // Unwraps the pointer, while asserting that memory hasn't been freed. The // function is allowed to crash on nullptr. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForDereference( - T* wrapped_ptr) { + 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); if (IsSupportedAndNotNull(address)) { @@ -246,22 +409,20 @@ // Unwraps the pointer, while asserting that memory hasn't been freed. The // function must handle nullptr gracefully. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForExtraction( - T* wrapped_ptr) { + static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) { return wrapped_ptr; } // Unwraps the pointer, without making an assertion on whether memory was // freed or not. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* UnsafelyUnwrapPtrForComparison( - T* wrapped_ptr) { + static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) { return wrapped_ptr; } // Upcasts the wrapped pointer. template <typename To, typename From> - static RAW_PTR_FUNC_ATTRIBUTES constexpr To* Upcast(From* wrapped_ptr) { + static ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) { static_assert(std::is_convertible<From*, To*>::value, "From must be convertible to To."); // Note, this cast may change the address if upcasting to base that lies in @@ -271,8 +432,7 @@ // Advance the wrapped pointer by |delta| bytes. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* Advance(T* wrapped_ptr, - ptrdiff_t delta_elem) { + static ALWAYS_INLINE T* Advance(T* wrapped_ptr, ptrdiff_t delta_elem) { #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) uintptr_t address = reinterpret_cast<uintptr_t>(wrapped_ptr); if (IsSupportedAndNotNull(address)) @@ -287,14 +447,13 @@ // memory was freed or not. // This method increments the reference count of the allocation slot. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* Duplicate(T* wrapped_ptr) { + static ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) { return WrapRawPtr(wrapped_ptr); } // This is for accounting only, used by unit tests. - static RAW_PTR_FUNC_ATTRIBUTES void IncrementSwapCountForTest() {} - static RAW_PTR_FUNC_ATTRIBUTES void - IncrementPointerToMemberOperatorCountForTest() {} + static ALWAYS_INLINE void IncrementSwapCountForTest() {} + static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {} private: // We've evaluated several strategies (inline nothing, various parts, or @@ -316,20 +475,19 @@ struct AsanBackupRefPtrImpl { // Wraps a pointer. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* WrapRawPtr(T* ptr) { + static ALWAYS_INLINE T* WrapRawPtr(T* ptr) { AsanCheckIfValidInstantiation(ptr); return ptr; } // Notifies the allocator when a wrapped pointer is being removed or replaced. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES void ReleaseWrappedPtr(T*) {} + static ALWAYS_INLINE void ReleaseWrappedPtr(T*) {} // Unwraps the pointer, while asserting that memory hasn't been freed. The // function is allowed to crash on nullptr. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForDereference( - T* wrapped_ptr) { + static ALWAYS_INLINE T* SafelyUnwrapPtrForDereference(T* wrapped_ptr) { AsanCheckIfValidDereference(wrapped_ptr); return wrapped_ptr; } @@ -337,8 +495,7 @@ // Unwraps the pointer, while asserting that memory hasn't been freed. The // function must handle nullptr gracefully. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* SafelyUnwrapPtrForExtraction( - T* wrapped_ptr) { + static ALWAYS_INLINE T* SafelyUnwrapPtrForExtraction(T* wrapped_ptr) { AsanCheckIfValidExtraction(wrapped_ptr); return wrapped_ptr; } @@ -346,14 +503,13 @@ // Unwraps the pointer, without making an assertion on whether memory was // freed or not. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* UnsafelyUnwrapPtrForComparison( - T* wrapped_ptr) { + static ALWAYS_INLINE T* UnsafelyUnwrapPtrForComparison(T* wrapped_ptr) { return wrapped_ptr; } // Upcasts the wrapped pointer. template <typename To, typename From> - static RAW_PTR_FUNC_ATTRIBUTES constexpr To* Upcast(From* wrapped_ptr) { + static ALWAYS_INLINE constexpr To* Upcast(From* wrapped_ptr) { static_assert(std::is_convertible<From*, To*>::value, "From must be convertible to To."); // Note, this cast may change the address if upcasting to base that lies in @@ -363,22 +519,20 @@ // Advance the wrapped pointer by |delta| bytes. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* Advance(T* wrapped_ptr, - ptrdiff_t delta_elems) { + static ALWAYS_INLINE T* Advance(T* wrapped_ptr, ptrdiff_t delta_elems) { return wrapped_ptr + delta_elems; } // Returns a copy of a wrapped pointer, without making an assertion on whether // memory was freed or not. template <typename T> - static RAW_PTR_FUNC_ATTRIBUTES T* Duplicate(T* wrapped_ptr) { + static ALWAYS_INLINE T* Duplicate(T* wrapped_ptr) { return wrapped_ptr; } // This is for accounting only, used by unit tests. - static RAW_PTR_FUNC_ATTRIBUTES void IncrementSwapCountForTest() {} - static RAW_PTR_FUNC_ATTRIBUTES void - IncrementPointerToMemberOperatorCountForTest() {} + static ALWAYS_INLINE void IncrementSwapCountForTest() {} + static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {} private: static BASE_EXPORT NOINLINE void AsanCheckIfValidInstantiation( @@ -494,14 +648,24 @@ // non-default move constructor/assignment. Thus, it's possible to get an error // where the pointer is not actually dangling, and have to work around the // compiler. We have not managed to construct such an example in Chromium yet. -template <typename T, #if BUILDFLAG(USE_BACKUP_REF_PTR) - typename Impl = internal::BackupRefPtrImpl> +using RawPtrMayDangle = internal::BackupRefPtrImpl</*AllowDangling=*/true>; +using RawPtrBanDanglingIfSupported = + internal::BackupRefPtrImpl</*AllowDangling=*/false>; #elif BUILDFLAG(USE_ASAN_BACKUP_REF_PTR) - typename Impl = internal::AsanBackupRefPtrImpl> +using RawPtrMayDangle = internal::AsanBackupRefPtrImpl; +using RawPtrBanDanglingIfSupported = internal::AsanBackupRefPtrImpl; +#elif defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS) +using RawPtrMayDangle = internal::MTECheckedPtrImpl< + internal::MTECheckedPtrImplPartitionAllocSupport>; +using RawPtrBanDanglingIfSupported = internal::MTECheckedPtrImpl< + internal::MTECheckedPtrImplPartitionAllocSupport>; #else - typename Impl = internal::RawPtrNoOpImpl> +using RawPtrMayDangle = internal::RawPtrNoOpImpl; +using RawPtrBanDanglingIfSupported = internal::RawPtrNoOpImpl; #endif + +template <typename T, typename Impl = RawPtrBanDanglingIfSupported> class TRIVIAL_ABI GSL_POINTER raw_ptr { public: static_assert(raw_ptr_traits::IsSupportedType<T>::value, @@ -509,18 +673,17 @@ #if BUILDFLAG(USE_BACKUP_REF_PTR) // BackupRefPtr requires a non-trivial default constructor, destructor, etc. - constexpr RAW_PTR_FUNC_ATTRIBUTES raw_ptr() noexcept - : wrapped_ptr_(nullptr) {} + constexpr ALWAYS_INLINE raw_ptr() noexcept : wrapped_ptr_(nullptr) {} - RAW_PTR_FUNC_ATTRIBUTES raw_ptr(const raw_ptr& p) noexcept + ALWAYS_INLINE raw_ptr(const raw_ptr& p) noexcept : wrapped_ptr_(Impl::Duplicate(p.wrapped_ptr_)) {} - RAW_PTR_FUNC_ATTRIBUTES raw_ptr(raw_ptr&& p) noexcept { + ALWAYS_INLINE raw_ptr(raw_ptr&& p) noexcept { wrapped_ptr_ = p.wrapped_ptr_; p.wrapped_ptr_ = nullptr; } - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(const raw_ptr& p) { + ALWAYS_INLINE raw_ptr& operator=(const raw_ptr& p) { // Duplicate before releasing, in case the pointer is assigned to itself. T* new_ptr = Impl::Duplicate(p.wrapped_ptr_); Impl::ReleaseWrappedPtr(wrapped_ptr_); @@ -528,7 +691,7 @@ return *this; } - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(raw_ptr&& p) { + ALWAYS_INLINE raw_ptr& operator=(raw_ptr&& p) { if (LIKELY(this != &p)) { Impl::ReleaseWrappedPtr(wrapped_ptr_); wrapped_ptr_ = p.wrapped_ptr_; @@ -537,7 +700,7 @@ return *this; } - RAW_PTR_FUNC_ATTRIBUTES ~raw_ptr() noexcept { + ALWAYS_INLINE ~raw_ptr() noexcept { Impl::ReleaseWrappedPtr(wrapped_ptr_); // Work around external issues where raw_ptr is used after destruction. wrapped_ptr_ = nullptr; @@ -550,31 +713,30 @@ // // TODO(lukasza): Always initialize |wrapped_ptr_|. Fix resulting build // errors. Analyze performance impact. - constexpr RAW_PTR_FUNC_ATTRIBUTES raw_ptr() noexcept = default; + constexpr ALWAYS_INLINE raw_ptr() noexcept = default; // In addition to nullptr_t ctor above, raw_ptr needs to have these // as |=default| or |constexpr| to avoid hitting -Wglobal-constructors in // cases like this: // struct SomeStruct { int int_field; raw_ptr<int> ptr_field; }; // SomeStruct g_global_var = { 123, nullptr }; - RAW_PTR_FUNC_ATTRIBUTES raw_ptr(const raw_ptr&) noexcept = default; - RAW_PTR_FUNC_ATTRIBUTES raw_ptr(raw_ptr&&) noexcept = default; - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(const raw_ptr&) noexcept = default; - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(raw_ptr&&) noexcept = default; + ALWAYS_INLINE raw_ptr(const raw_ptr&) noexcept = default; + ALWAYS_INLINE raw_ptr(raw_ptr&&) noexcept = default; + ALWAYS_INLINE raw_ptr& operator=(const raw_ptr&) noexcept = default; + ALWAYS_INLINE raw_ptr& operator=(raw_ptr&&) noexcept = default; - RAW_PTR_FUNC_ATTRIBUTES ~raw_ptr() = default; + ALWAYS_INLINE ~raw_ptr() = default; #endif // BUILDFLAG(USE_BACKUP_REF_PTR) // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr. // NOLINTNEXTLINE(google-explicit-constructor) - constexpr RAW_PTR_FUNC_ATTRIBUTES raw_ptr(std::nullptr_t) noexcept + constexpr ALWAYS_INLINE raw_ptr(std::nullptr_t) noexcept : wrapped_ptr_(nullptr) {} // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr. // NOLINTNEXTLINE(google-explicit-constructor) - RAW_PTR_FUNC_ATTRIBUTES raw_ptr(T* p) noexcept - : wrapped_ptr_(Impl::WrapRawPtr(p)) {} + ALWAYS_INLINE raw_ptr(T* p) noexcept : wrapped_ptr_(Impl::WrapRawPtr(p)) {} // Deliberately implicit in order to support implicit upcast. template <typename U, @@ -582,7 +744,7 @@ std::is_convertible<U*, T*>::value && !std::is_void<typename std::remove_cv<T>::type>::value>> // NOLINTNEXTLINE(google-explicit-constructor) - RAW_PTR_FUNC_ATTRIBUTES raw_ptr(const raw_ptr<U, Impl>& ptr) noexcept + ALWAYS_INLINE raw_ptr(const raw_ptr<U, Impl>& ptr) noexcept : wrapped_ptr_( Impl::Duplicate(Impl::template Upcast<T, U>(ptr.wrapped_ptr_))) {} // Deliberately implicit in order to support implicit upcast. @@ -591,19 +753,19 @@ std::is_convertible<U*, T*>::value && !std::is_void<typename std::remove_cv<T>::type>::value>> // NOLINTNEXTLINE(google-explicit-constructor) - RAW_PTR_FUNC_ATTRIBUTES raw_ptr(raw_ptr<U, Impl>&& ptr) noexcept + ALWAYS_INLINE raw_ptr(raw_ptr<U, Impl>&& ptr) noexcept : wrapped_ptr_(Impl::template Upcast<T, U>(ptr.wrapped_ptr_)) { #if BUILDFLAG(USE_BACKUP_REF_PTR) ptr.wrapped_ptr_ = nullptr; #endif } - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(std::nullptr_t) noexcept { + ALWAYS_INLINE raw_ptr& operator=(std::nullptr_t) noexcept { Impl::ReleaseWrappedPtr(wrapped_ptr_); wrapped_ptr_ = nullptr; return *this; } - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(T* p) noexcept { + ALWAYS_INLINE raw_ptr& operator=(T* p) noexcept { Impl::ReleaseWrappedPtr(wrapped_ptr_); wrapped_ptr_ = Impl::WrapRawPtr(p); return *this; @@ -614,8 +776,7 @@ typename Unused = std::enable_if_t< std::is_convertible<U*, T*>::value && !std::is_void<typename std::remove_cv<T>::type>::value>> - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=( - const raw_ptr<U, Impl>& ptr) noexcept { + ALWAYS_INLINE raw_ptr& operator=(const raw_ptr<U, Impl>& ptr) noexcept { // Make sure that pointer isn't assigned to itself (look at pointer address, // not its value). #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) @@ -631,7 +792,7 @@ typename Unused = std::enable_if_t< std::is_convertible<U*, T*>::value && !std::is_void<typename std::remove_cv<T>::type>::value>> - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator=(raw_ptr<U, Impl>&& ptr) noexcept { + ALWAYS_INLINE raw_ptr& operator=(raw_ptr<U, Impl>&& ptr) noexcept { // Make sure that pointer isn't assigned to itself (look at pointer address, // not its value). #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS) @@ -648,19 +809,17 @@ // Avoid using. The goal of raw_ptr is to be as close to raw pointer as // possible, so use it only if absolutely necessary (e.g. for const_cast). - RAW_PTR_FUNC_ATTRIBUTES T* get() const { return GetForExtraction(); } + ALWAYS_INLINE T* get() const { return GetForExtraction(); } - explicit RAW_PTR_FUNC_ATTRIBUTES operator bool() const { - return !!wrapped_ptr_; - } + explicit ALWAYS_INLINE operator bool() const { return !!wrapped_ptr_; } template <typename U = T, typename Unused = std::enable_if_t< !std::is_void<typename std::remove_cv<U>::type>::value>> - RAW_PTR_FUNC_ATTRIBUTES U& operator*() const { + ALWAYS_INLINE U& operator*() const { return *GetForDereference(); } - RAW_PTR_FUNC_ATTRIBUTES T* operator->() const { return GetForDereference(); } + ALWAYS_INLINE T* operator->() const { return GetForDereference(); } // Disables `(my_raw_ptr->*pmf)(...)` as a workaround for // the ICE in GCC parsing the code, reported at @@ -670,37 +829,37 @@ // Deliberately implicit, because raw_ptr is supposed to resemble raw ptr. // NOLINTNEXTLINE(runtime/explicit) - RAW_PTR_FUNC_ATTRIBUTES operator T*() const { return GetForExtraction(); } + ALWAYS_INLINE operator T*() const { return GetForExtraction(); } template <typename U> - explicit RAW_PTR_FUNC_ATTRIBUTES operator U*() const { + explicit ALWAYS_INLINE operator U*() const { // This operator may be invoked from static_cast, meaning the types may not // be implicitly convertible, hence the need for static_cast here. return static_cast<U*>(GetForExtraction()); } - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator++() { + ALWAYS_INLINE raw_ptr& operator++() { wrapped_ptr_ = Impl::Advance(wrapped_ptr_, 1); return *this; } - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator--() { + ALWAYS_INLINE raw_ptr& operator--() { wrapped_ptr_ = Impl::Advance(wrapped_ptr_, -1); return *this; } - RAW_PTR_FUNC_ATTRIBUTES raw_ptr operator++(int /* post_increment */) { + ALWAYS_INLINE raw_ptr operator++(int /* post_increment */) { raw_ptr result = *this; ++(*this); return result; } - RAW_PTR_FUNC_ATTRIBUTES raw_ptr operator--(int /* post_decrement */) { + ALWAYS_INLINE raw_ptr operator--(int /* post_decrement */) { raw_ptr result = *this; --(*this); return result; } - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator+=(ptrdiff_t delta_elems) { + ALWAYS_INLINE raw_ptr& operator+=(ptrdiff_t delta_elems) { wrapped_ptr_ = Impl::Advance(wrapped_ptr_, delta_elems); return *this; } - RAW_PTR_FUNC_ATTRIBUTES raw_ptr& operator-=(ptrdiff_t delta_elems) { + ALWAYS_INLINE raw_ptr& operator-=(ptrdiff_t delta_elems) { return *this += -delta_elems; } @@ -708,13 +867,25 @@ // raw delete calls, this avoids the raw_ptr to be temporarily dangling // during the free operation, which will lead to taking the slower path that // involves quarantine. - RAW_PTR_FUNC_ATTRIBUTES void ClearAndDelete() noexcept { + 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; } - RAW_PTR_FUNC_ATTRIBUTES void ClearAndDeleteArray() noexcept { + 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; } @@ -733,118 +904,121 @@ // because a comparison operator defined inline would not be allowed to call // `raw_ptr<U>`'s private `GetForComparison()` method. template <typename U, typename V, typename I> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator==(const raw_ptr<U, I>& lhs, - const raw_ptr<V, I>& rhs); + friend ALWAYS_INLINE bool operator==(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs); template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator!=(const raw_ptr& lhs, - const raw_ptr<U, Impl>& rhs) { + friend ALWAYS_INLINE bool operator!=(const raw_ptr& lhs, + const raw_ptr<U, Impl>& rhs) { return !(lhs == rhs); } template <typename U, typename V, typename I> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator<(const raw_ptr<U, I>& lhs, - const raw_ptr<V, I>& rhs); + friend ALWAYS_INLINE bool operator<(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs); template <typename U, typename V, typename I> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator>(const raw_ptr<U, I>& lhs, - const raw_ptr<V, I>& rhs); + friend ALWAYS_INLINE bool operator>(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs); template <typename U, typename V, typename I> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator<=(const raw_ptr<U, I>& lhs, - const raw_ptr<V, I>& rhs); + friend ALWAYS_INLINE bool operator<=(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs); template <typename U, typename V, typename I> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator>=(const raw_ptr<U, I>& lhs, - const raw_ptr<V, I>& rhs); + friend ALWAYS_INLINE bool operator>=(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs); // Comparisons with U*. These operators also handle the case where the RHS is // T*. template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator==(const raw_ptr& lhs, U* rhs) { + friend ALWAYS_INLINE bool operator==(const raw_ptr& lhs, U* rhs) { return lhs.GetForComparison() == rhs; } template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator!=(const raw_ptr& lhs, U* rhs) { + friend ALWAYS_INLINE bool operator!=(const raw_ptr& lhs, U* rhs) { return !(lhs == rhs); } template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator==(U* lhs, const raw_ptr& rhs) { + friend ALWAYS_INLINE bool operator==(U* lhs, const raw_ptr& rhs) { return rhs == lhs; // Reverse order to call the operator above. } template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator!=(U* lhs, const raw_ptr& rhs) { + friend ALWAYS_INLINE bool operator!=(U* lhs, const raw_ptr& rhs) { return rhs != lhs; // Reverse order to call the operator above. } template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator<(const raw_ptr& lhs, U* rhs) { + friend ALWAYS_INLINE bool operator<(const raw_ptr& lhs, U* rhs) { return lhs.GetForComparison() < rhs; } template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator<=(const raw_ptr& lhs, U* rhs) { + friend ALWAYS_INLINE bool operator<=(const raw_ptr& lhs, U* rhs) { return lhs.GetForComparison() <= rhs; } template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator>(const raw_ptr& lhs, U* rhs) { + friend ALWAYS_INLINE bool operator>(const raw_ptr& lhs, U* rhs) { return lhs.GetForComparison() > rhs; } template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator>=(const raw_ptr& lhs, U* rhs) { + friend ALWAYS_INLINE bool operator>=(const raw_ptr& lhs, U* rhs) { return lhs.GetForComparison() >= rhs; } template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator<(U* lhs, const raw_ptr& rhs) { + friend ALWAYS_INLINE bool operator<(U* lhs, const raw_ptr& rhs) { return lhs < rhs.GetForComparison(); } template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator<=(U* lhs, const raw_ptr& rhs) { + friend ALWAYS_INLINE bool operator<=(U* lhs, const raw_ptr& rhs) { return lhs <= rhs.GetForComparison(); } template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator>(U* lhs, const raw_ptr& rhs) { + friend ALWAYS_INLINE bool operator>(U* lhs, const raw_ptr& rhs) { return lhs > rhs.GetForComparison(); } template <typename U> - friend RAW_PTR_FUNC_ATTRIBUTES bool operator>=(U* lhs, const raw_ptr& rhs) { + friend ALWAYS_INLINE bool operator>=(U* lhs, const raw_ptr& rhs) { return lhs >= rhs.GetForComparison(); } // Comparisons with `std::nullptr_t`. - friend RAW_PTR_FUNC_ATTRIBUTES bool operator==(const raw_ptr& lhs, - std::nullptr_t) { + friend ALWAYS_INLINE bool operator==(const raw_ptr& lhs, std::nullptr_t) { return !lhs; } - friend RAW_PTR_FUNC_ATTRIBUTES bool operator!=(const raw_ptr& lhs, - std::nullptr_t) { + friend ALWAYS_INLINE bool operator!=(const raw_ptr& lhs, std::nullptr_t) { return !!lhs; // Use !! otherwise the costly implicit cast will be used. } - friend RAW_PTR_FUNC_ATTRIBUTES bool operator==(std::nullptr_t, - const raw_ptr& rhs) { + friend ALWAYS_INLINE bool operator==(std::nullptr_t, const raw_ptr& rhs) { return !rhs; } - friend RAW_PTR_FUNC_ATTRIBUTES bool operator!=(std::nullptr_t, - const raw_ptr& rhs) { + friend ALWAYS_INLINE bool operator!=(std::nullptr_t, const raw_ptr& rhs) { return !!rhs; // Use !! otherwise the costly implicit cast will be used. } - friend RAW_PTR_FUNC_ATTRIBUTES void swap(raw_ptr& lhs, - raw_ptr& rhs) noexcept { + friend ALWAYS_INLINE void swap(raw_ptr& lhs, raw_ptr& rhs) noexcept { Impl::IncrementSwapCountForTest(); std::swap(lhs.wrapped_ptr_, rhs.wrapped_ptr_); } + // If T can be serialised into trace, its alias is also + // serialisable. + template <class U = T> + typename perfetto::check_traced_value_support<U>::type WriteIntoTrace( + perfetto::TracedValue&& context) const { + perfetto::WriteIntoTracedValue(std::move(context), get()); + } + private: // This getter is meant for situations where the pointer is meant to be // dereferenced. It is allowed to crash on nullptr (it may or may not), // because it knows that the caller will crash on nullptr. - RAW_PTR_FUNC_ATTRIBUTES T* GetForDereference() const { + ALWAYS_INLINE T* GetForDereference() const { return Impl::SafelyUnwrapPtrForDereference(wrapped_ptr_); } // This getter is meant for situations where the raw pointer is meant to be // extracted outside of this class, but not necessarily with an intention to // dereference. It mustn't crash on nullptr. - RAW_PTR_FUNC_ATTRIBUTES T* GetForExtraction() const { + ALWAYS_INLINE T* GetForExtraction() const { return Impl::SafelyUnwrapPtrForExtraction(wrapped_ptr_); } // This getter is meant *only* for situations where the pointer is meant to be // compared (guaranteeing no dereference or extraction outside of this class). // Any verifications can and should be skipped for performance reasons. - RAW_PTR_FUNC_ATTRIBUTES T* GetForComparison() const { + ALWAYS_INLINE T* GetForComparison() const { return Impl::UnsafelyUnwrapPtrForComparison(wrapped_ptr_); } @@ -855,32 +1029,32 @@ }; template <typename U, typename V, typename I> -RAW_PTR_FUNC_ATTRIBUTES bool operator==(const raw_ptr<U, I>& lhs, - const raw_ptr<V, I>& rhs) { +ALWAYS_INLINE bool operator==(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs) { return lhs.GetForComparison() == rhs.GetForComparison(); } template <typename U, typename V, typename I> -RAW_PTR_FUNC_ATTRIBUTES bool operator<(const raw_ptr<U, I>& lhs, - const raw_ptr<V, I>& rhs) { +ALWAYS_INLINE bool operator<(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs) { return lhs.GetForComparison() < rhs.GetForComparison(); } template <typename U, typename V, typename I> -RAW_PTR_FUNC_ATTRIBUTES bool operator>(const raw_ptr<U, I>& lhs, - const raw_ptr<V, I>& rhs) { +ALWAYS_INLINE bool operator>(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs) { return lhs.GetForComparison() > rhs.GetForComparison(); } template <typename U, typename V, typename I> -RAW_PTR_FUNC_ATTRIBUTES bool operator<=(const raw_ptr<U, I>& lhs, - const raw_ptr<V, I>& rhs) { +ALWAYS_INLINE bool operator<=(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs) { return lhs.GetForComparison() <= rhs.GetForComparison(); } template <typename U, typename V, typename I> -RAW_PTR_FUNC_ATTRIBUTES bool operator>=(const raw_ptr<U, I>& lhs, - const raw_ptr<V, I>& rhs) { +ALWAYS_INLINE bool operator>=(const raw_ptr<U, I>& lhs, + const raw_ptr<V, I>& rhs) { return lhs.GetForComparison() >= rhs.GetForComparison(); } @@ -888,6 +1062,17 @@ using gurl_base::raw_ptr; +// DisableDanglingPtrDetection option for raw_ptr annotates +// "intentional-and-safe" dangling pointers. It is meant to be used at the +// margin, only if there is no better way to re-architecture the code. +// +// Usage: +// raw_ptr<T, DisableDanglingPtrDetection> dangling_ptr; +// +// When using it, please provide a justification about what guarantees it will +// never be dereferenced after becoming dangling. +using DisableDanglingPtrDetection = gurl_base::RawPtrMayDangle; + namespace std { // Override so set/map lookups do not create extra raw_ptr. This also allows
diff --git a/base/ranges/algorithm.h b/base/ranges/algorithm.h index b405d2f..f7a23c4 100644 --- a/base/ranges/algorithm.h +++ b/base/ranges/algorithm.h
@@ -63,9 +63,9 @@ private: template <typename ProjT, typename ProjU, typename T, typename U> - using InvokeResult = invoke_result_t<Pred&, - invoke_result_t<ProjT&, T&&>, - invoke_result_t<ProjU&, U&&>>; + using InvokeResult = std::invoke_result_t<Pred&, + std::invoke_result_t<ProjT&, T&&>, + std::invoke_result_t<ProjU&, U&&>>; template <typename T, typename U, typename = InvokeResult<Proj1, Proj2, T, U>> constexpr std::pair<Proj1&, Proj2&> GetProjs(priority_tag<3>) const {
diff --git a/base/strings/abseil_string_number_conversions.cc b/base/strings/abseil_string_number_conversions.cc index 9ab1303..aab4905 100644 --- a/base/strings/abseil_string_number_conversions.cc +++ b/base/strings/abseil_string_number_conversions.cc
@@ -10,6 +10,10 @@ namespace gurl_base { +bool StringToUint128(StringPiece input, absl::uint128* output) { + return internal::StringToIntImpl(input, *output); +} + bool HexStringToUInt128(StringPiece input, absl::uint128* output) { return internal::HexStringToIntImpl(input, *output); }
diff --git a/base/strings/abseil_string_number_conversions.h b/base/strings/abseil_string_number_conversions.h index 7eb927d..85d6d29 100644 --- a/base/strings/abseil_string_number_conversions.h +++ b/base/strings/abseil_string_number_conversions.h
@@ -15,7 +15,11 @@ namespace gurl_base { // Best effort conversion, see `gurl_base::StringToInt()` for restrictions. -// Will only successfully parse hex values that will fit into |output|. +// Will only successfully parse values that will fit into `output`. +BASE_EXPORT bool StringToUint128(StringPiece input, absl::uint128* output); + +// Best effort conversion, see `gurl_base::StringToInt()` for restrictions. +// Will only successfully parse hex values that will fit into `output`. // The string is not required to start with 0x. BASE_EXPORT bool HexStringToUInt128(StringPiece input, absl::uint128* output);
diff --git a/base/strings/abseil_string_number_conversions_unittest.cc b/base/strings/abseil_string_number_conversions_unittest.cc index 3c68cde..5873e79 100644 --- a/base/strings/abseil_string_number_conversions_unittest.cc +++ b/base/strings/abseil_string_number_conversions_unittest.cc
@@ -8,13 +8,89 @@ #include <limits> -#include "base/cxx17_backports.h" #include "base/strings/string_piece.h" #include "testing/gtest/include/gtest/gtest.h" #include "absl/numeric/int128.h" namespace gurl_base { +TEST(AbseilStringNumberConversionsTest, StringToUint128) { + // Test cases adapted from `StringNumberConversionsTest.StringToUint64`. + static const struct { + std::string input; + absl::uint128 output; + bool success; + } cases[] = { + {"0", 0, true}, + {"42", 42, true}, + {"-2147483648", 0, false}, + {"2147483647", INT_MAX, true}, + {"-2147483649", 0, false}, + {"-99999999999", 0, false}, + {"2147483648", UINT64_C(2147483648), true}, + {"99999999999", UINT64_C(99999999999), true}, + {"9223372036854775807", std::numeric_limits<int64_t>::max(), true}, + {"-9223372036854775808", 0, false}, + {"09", 9, true}, + {"-09", 0, false}, + {"", 0, false}, + {" 42", 42, false}, + {"42 ", 42, false}, + {"0x42", 0, false}, + {"\t\n\v\f\r 42", 42, false}, + {"blah42", 0, false}, + {"42blah", 42, false}, + {"blah42blah", 0, false}, + {"-273.15", 0, false}, + {"+98.6", 98, false}, + {"--123", 0, false}, + {"++123", 0, false}, + {"-+123", 0, false}, + {"+-123", 0, false}, + {"-", 0, false}, + {"-9223372036854775809", 0, false}, + {"-99999999999999999999", 0, false}, + {"9223372036854775808", UINT64_C(9223372036854775808), true}, + {"99999999999999999999", + absl::MakeUint128(/*high=*/5, /*low=*/UINT64_C(7766279631452241919)), + true}, + {"18446744073709551615", std::numeric_limits<uint64_t>::max(), true}, + {"18446744073709551616", absl::MakeUint128(/*high=*/1, /*low=*/0), true}, + {"123456789012345678901234567890123456789", + absl::MakeUint128(/*high=*/UINT64_C(6692605942763486917), + /*low=*/UINT64_C(12312739301371248917)), + true}, + {"-170141183460469231731687303715884105728", 0, false}, + {"-170141183460469231731687303715884105729", 0, false}, + {"-999999999999999999999999999999999999999", 0, false}, + {"170141183460469231731687303715884105727", + std::numeric_limits<absl::int128>::max(), true}, + {"340282366920938463463374607431768211455", + std::numeric_limits<absl::uint128>::max(), true}, + {"340282366920938463463374607431768211456", + std::numeric_limits<absl::uint128>::max(), false}, + {"999999999999999999999999999999999999999", + std::numeric_limits<absl::uint128>::max(), false}, + }; + + for (const auto& i : cases) { + absl::uint128 output = 0; + EXPECT_EQ(i.success, StringToUint128(i.input, &output)) << i.input; + EXPECT_EQ(i.output, output); + } + + // One additional test to verify that conversion of numbers in strings with + // embedded NUL characters. The NUL and extra data after it should be + // interpreted as junk after the number. + const char input[] = + "6\0" + "6"; + std::string input_string(input, std::size(input) - 1); + absl::uint128 output; + EXPECT_FALSE(StringToUint128(input_string, &output)); + EXPECT_EQ(6U, output); +} + TEST(AbseilStringNumberConversionsTest, HexStringToUInt128) { // Test cases adapted from `StringNumberConversionsTest.HexStringToUint64`. static const struct { @@ -93,7 +169,7 @@ const char input[] = "0xc0ffee\0" "9"; - std::string input_string(input, gurl_base::size(input) - 1); + std::string input_string(input, std::size(input) - 1); absl::uint128 output; EXPECT_FALSE(HexStringToUInt128(input_string, &output)); EXPECT_EQ(0xc0ffeeU, output);
diff --git a/base/strings/char_traits.h b/base/strings/char_traits.h deleted file mode 100644 index fe01c53..0000000 --- a/base/strings/char_traits.h +++ /dev/null
@@ -1,112 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef BASE_STRINGS_CHAR_TRAITS_H_ -#define BASE_STRINGS_CHAR_TRAITS_H_ - -#include <stddef.h> - -#include <string> - -#include "base/compiler_specific.h" - -namespace gurl_base { - -// constexpr version of http://en.cppreference.com/w/cpp/string/char_traits. -// This currently just implements the bits needed to support a (mostly) -// constexpr StringPiece. -// -// TODO(dcheng): Once we switch to C++17, most methods will become constexpr and -// we can switch over to using the one in the standard library. -template <typename T> -struct CharTraits { - // Performs a lexographical comparison of the first N characters of |s1| and - // |s2|. Returns 0 if equal, -1 if |s1| is less than |s2|, and 1 if |s1| is - // greater than |s2|. - static constexpr int compare(const T* s1, const T* s2, size_t n) noexcept; - - // Returns the length of |s|, assuming null termination (and not including the - // terminating null). - static constexpr size_t length(const T* s) noexcept; - - // Searches for character |c| within the first |n| characters of the sequence - // pointed to by |s|. - static constexpr const T* find(const T* s, size_t n, T c); -}; - -template <typename T> -constexpr int CharTraits<T>::compare(const T* s1, - const T* s2, - size_t n) noexcept { - // Comparison with operator < fails, because of signed/unsigned - // mismatch, https://crbug.com/941696 - // std::char_traits<T>::lt is guaranteed to be constexpr in C++14: - // https://timsong-cpp.github.io/cppwp/n4140/char.traits.specializations#char - for (; n; --n, ++s1, ++s2) { - if (std::char_traits<T>::lt(*s1, *s2)) - return -1; - if (std::char_traits<T>::lt(*s2, *s1)) - return 1; - } - return 0; -} - -template <typename T> -constexpr size_t CharTraits<T>::length(const T* s) noexcept { - size_t i = 0; - for (; *s; ++s) - ++i; - return i; -} - -template <typename T> -constexpr const T* CharTraits<T>::find(const T* s, size_t n, T c) { - for (; n; --n, ++s) { - if (std::char_traits<T>::eq(*s, c)) - return s; - } - return nullptr; -} - -// char and wchar_t specialization of CharTraits that can use clang's constexpr -// instrinsics, where available. -#if HAS_FEATURE(cxx_constexpr_string_builtins) -template <> -struct CharTraits<char> { - static constexpr int compare(const char* s1, - const char* s2, - size_t n) noexcept { - return __builtin_memcmp(s1, s2, n); - } - - static constexpr size_t length(const char* s) noexcept { - return __builtin_strlen(s); - } - - static constexpr const char* find(const char* s, size_t n, char c) { - return __builtin_char_memchr(s, c, n); - } -}; - -template <> -struct CharTraits<wchar_t> { - static constexpr int compare(const wchar_t* s1, - const wchar_t* s2, - size_t n) noexcept { - return __builtin_wmemcmp(s1, s2, n); - } - - static constexpr size_t length(const wchar_t* s) noexcept { - return __builtin_wcslen(s); - } - - static constexpr const wchar_t* find(const wchar_t* s, size_t n, wchar_t c) { - return __builtin_wmemchr(s, c, n); - } -}; -#endif - -} // namespace base - -#endif // BASE_STRINGS_CHAR_TRAITS_H_
diff --git a/base/strings/char_traits_unittest.cc b/base/strings/char_traits_unittest.cc deleted file mode 100644 index d735d4a..0000000 --- a/base/strings/char_traits_unittest.cc +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/strings/char_traits.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace gurl_base { - -TEST(CharTraitsTest, CharCompare) { - static_assert(CharTraits<char>::compare("abc", "def", 3) == -1, ""); - static_assert(CharTraits<char>::compare("def", "def", 3) == 0, ""); - static_assert(CharTraits<char>::compare("ghi", "def", 3) == 1, ""); -} - -TEST(CharTraitsTest, CharLength) { - static_assert(CharTraits<char>::length("") == 0, ""); - static_assert(CharTraits<char>::length("abc") == 3, ""); -} - -TEST(CharTraitsTest, Char16TCompare) { - static_assert(CharTraits<char16_t>::compare(u"abc", u"def", 3) == -1, ""); - static_assert(CharTraits<char16_t>::compare(u"def", u"def", 3) == 0, ""); - static_assert(CharTraits<char16_t>::compare(u"ghi", u"def", 3) == 1, ""); -} - -TEST(CharTraitsTest, Char16TLength) { - static_assert(CharTraits<char16_t>::length(u"abc") == 3, ""); -} - -} // namespace base
diff --git a/base/strings/escape.cc b/base/strings/escape.cc index ff6f6d8..8324aae 100644 --- a/base/strings/escape.cc +++ b/base/strings/escape.cc
@@ -4,15 +4,145 @@ #include "base/strings/escape.h" +#include <ostream> + +#include "polyfills/base/check_op.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversion_utils.h" +#include "base/strings/utf_string_conversions.h" #include "base/third_party/icu/icu_utf.h" namespace gurl_base { namespace { +const char kHexString[] = "0123456789ABCDEF"; +inline char IntToHex(int i) { + GURL_DCHECK_GE(i, 0) << i << " not a hex value"; + GURL_DCHECK_LE(i, 15) << i << " not a hex value"; + return kHexString[i]; +} + +// A fast bit-vector map for ascii characters. +// +// Internally stores 256 bits in an array of 8 ints. +// Does quick bit-flicking to lookup needed characters. +struct Charmap { + bool Contains(unsigned char c) const { + return ((map[c >> 5] & (1 << (c & 31))) != 0); + } + + uint32_t map[8]; +}; + +// Given text to escape and a Charmap defining which values to escape, +// return an escaped string. If use_plus is true, spaces are converted +// to +, otherwise, if spaces are in the charmap, they are converted to +// %20. And if keep_escaped is true, %XX will be kept as it is, otherwise, if +// '%' is in the charmap, it is converted to %25. +std::string Escape(StringPiece text, + const Charmap& charmap, + bool use_plus, + bool keep_escaped = false) { + std::string escaped; + escaped.reserve(text.length() * 3); + for (unsigned int i = 0; i < text.length(); ++i) { + unsigned char c = static_cast<unsigned char>(text[i]); + if (use_plus && ' ' == c) { + escaped.push_back('+'); + } else if (keep_escaped && '%' == c && i + 2 < text.length() && + IsHexDigit(text[i + 1]) && IsHexDigit(text[i + 2])) { + escaped.push_back('%'); + } else if (charmap.Contains(c)) { + escaped.push_back('%'); + escaped.push_back(IntToHex(c >> 4)); + escaped.push_back(IntToHex(c & 0xf)); + } else { + escaped.push_back(c); + } + } + return escaped; +} + +// Convert a character |c| to a form that will not be mistaken as HTML. +template <class str> +void AppendEscapedCharForHTMLImpl(typename str::value_type c, str* output) { + static constexpr struct { + char key; + StringPiece replacement; + } kCharsToEscape[] = { + {'<', "<"}, {'>', ">"}, {'&', "&"}, + {'"', """}, {'\'', "'"}, + }; + for (const auto& char_to_escape : kCharsToEscape) { + if (c == char_to_escape.key) { + output->append(std::begin(char_to_escape.replacement), + std::end(char_to_escape.replacement)); + return; + } + } + output->push_back(c); +} + +// Convert |input| string to a form that will not be interpreted as HTML. +template <typename T, typename CharT = typename T::value_type> +std::basic_string<CharT> EscapeForHTMLImpl(T input) { + std::basic_string<CharT> result; + result.reserve(input.size()); // Optimize for no escaping. + + for (auto c : input) { + AppendEscapedCharForHTMLImpl(c, &result); + } + + return result; +} + +// Everything except alphanumerics and -._~ +// See RFC 3986 for the list of unreserved characters. +static const Charmap kUnreservedCharmap = { + {0xffffffffL, 0xfc009fffL, 0x78000001L, 0xb8000001L, 0xffffffffL, + 0xffffffffL, 0xffffffffL, 0xffffffffL}}; + +// Everything except alphanumerics and !'()*-._~ +// See RFC 2396 for the list of reserved characters. +static const Charmap kQueryCharmap = {{0xffffffffL, 0xfc00987dL, 0x78000001L, + 0xb8000001L, 0xffffffffL, 0xffffffffL, + 0xffffffffL, 0xffffffffL}}; + +// non-printable, non-7bit, and (including space) "#%:<>?[\]^`{|} +static const Charmap kPathCharmap = {{0xffffffffL, 0xd400002dL, 0x78000000L, + 0xb8000001L, 0xffffffffL, 0xffffffffL, + 0xffffffffL, 0xffffffffL}}; + +#if BUILDFLAG(IS_APPLE) +// non-printable, non-7bit, and (including space) "#%<>[\]^`{|} +static const Charmap kNSURLCharmap = {{0xffffffffL, 0x5000002dL, 0x78000000L, + 0xb8000001L, 0xffffffffL, 0xffffffffL, + 0xffffffffL, 0xffffffffL}}; +#endif // BUILDFLAG(IS_APPLE) + +// non-printable, non-7bit, and (including space) ?>=<;+'&%$#"![\]^`{|} +static const Charmap kUrlEscape = {{0xffffffffL, 0xf80008fdL, 0x78000001L, + 0xb8000001L, 0xffffffffL, 0xffffffffL, + 0xffffffffL, 0xffffffffL}}; + +// non-7bit, as well as %. +static const Charmap kNonASCIICharmapAndPercent = { + {0x00000000L, 0x00000020L, 0x00000000L, 0x00000000L, 0xffffffffL, + 0xffffffffL, 0xffffffffL, 0xffffffffL}}; + +// non-7bit +static const Charmap kNonASCIICharmap = {{0x00000000L, 0x00000000L, 0x00000000L, + 0x00000000L, 0xffffffffL, 0xffffffffL, + 0xffffffffL, 0xffffffffL}}; + +// Everything except alphanumerics, the reserved characters(;/?:@&=+$,) and +// !'()*-._~#[] +static const Charmap kExternalHandlerCharmap = { + {0xffffffffL, 0x50000025L, 0x50000000L, 0xb8000001L, 0xffffffffL, + 0xffffffffL, 0xffffffffL, 0xffffffffL}}; + // Contains nonzero when the corresponding character is unescapable for normal // URLs. These characters are the ones that may change the parsing of a URL, so // we don't want to unescape them sometimes. In many case we won't want to @@ -96,7 +226,7 @@ // reach max character length number of bytes, or hit an unescaped // character. No need to check length of escaped_text, as // UnescapeUnsignedByteAtIndex checks lengths. - while (num_bytes < size(bytes) && + while (num_bytes < std::size(bytes) && UnescapeUnsignedByteAtIndex(escaped_text, index + num_bytes * 3, &bytes[num_bytes]) && CBU8_IS_TRAIL(bytes[num_bytes])) { @@ -331,6 +461,52 @@ } // namespace +std::string EscapeAllExceptUnreserved(StringPiece text) { + return Escape(text, kUnreservedCharmap, false); +} + +std::string EscapeQueryParamValue(StringPiece text, bool use_plus) { + return Escape(text, kQueryCharmap, use_plus); +} + +std::string EscapePath(StringPiece path) { + return Escape(path, kPathCharmap, false); +} + +#if BUILDFLAG(IS_APPLE) +std::string EscapeNSURLPrecursor(StringPiece precursor) { + return Escape(precursor, kNSURLCharmap, false, true); +} +#endif // BUILDFLAG(IS_APPLE) + +std::string EscapeUrlEncodedData(StringPiece path, bool use_plus) { + return Escape(path, kUrlEscape, use_plus); +} + +std::string EscapeNonASCIIAndPercent(StringPiece input) { + return Escape(input, kNonASCIICharmapAndPercent, false); +} + +std::string EscapeNonASCII(StringPiece input) { + return Escape(input, kNonASCIICharmap, false); +} + +std::string EscapeExternalHandlerValue(StringPiece text) { + return Escape(text, kExternalHandlerCharmap, false, true); +} + +void AppendEscapedCharForHTML(char c, std::string* output) { + AppendEscapedCharForHTMLImpl(c, output); +} + +std::string EscapeForHTML(StringPiece input) { + return EscapeForHTMLImpl(input); +} + +std::u16string EscapeForHTML(StringPiece16 input) { + return EscapeForHTMLImpl(input); +} + std::string UnescapeURLComponent(StringPiece escaped_text, UnescapeRule::Type rules) { return UnescapeURLWithAdjustmentsImpl(escaped_text, rules, nullptr); @@ -441,4 +617,39 @@ return false; } -} // namespace base \ No newline at end of file +std::u16string UnescapeForHTML(StringPiece16 input) { + static const struct { + const char* ampersand_code; + const char replacement; + } kEscapeToChars[] = { + {"<", '<'}, {">", '>'}, {"&", '&'}, + {""", '"'}, {"'", '\''}, + }; + constexpr size_t kEscapeToCharsCount = std::size(kEscapeToChars); + + if (input.find(u"&") == std::string::npos) + return std::u16string(input); + + std::u16string ampersand_chars[kEscapeToCharsCount]; + std::u16string text(input); + for (std::u16string::iterator iter = text.begin(); iter != text.end(); + ++iter) { + if (*iter == '&') { + // Potential ampersand encode char. + size_t index = iter - text.begin(); + for (size_t i = 0; i < std::size(kEscapeToChars); i++) { + if (ampersand_chars[i].empty()) { + ampersand_chars[i] = ASCIIToUTF16(kEscapeToChars[i].ampersand_code); + } + if (text.find(ampersand_chars[i], index) == index) { + text.replace(iter, iter + ampersand_chars[i].length(), 1, + kEscapeToChars[i].replacement); + break; + } + } + } + } + return text; +} + +} // namespace base
diff --git a/base/strings/escape.h b/base/strings/escape.h index 96ce110..57f2f9a 100644 --- a/base/strings/escape.h +++ b/base/strings/escape.h
@@ -16,6 +16,58 @@ namespace gurl_base { +// Escaping -------------------------------------------------------------------- + +// Escapes all characters except unreserved characters. Unreserved characters, +// as defined in RFC 3986, include alphanumerics and -._~ +BASE_EXPORT std::string EscapeAllExceptUnreserved(StringPiece text); + +// Escapes characters in text suitable for use as a query parameter value. +// We %XX everything except alphanumerics and -_.!~*'() +// Spaces change to "+" unless you pass usePlus=false. +// This is basically the same as encodeURIComponent in javascript. +BASE_EXPORT std::string EscapeQueryParamValue(StringPiece text, bool use_plus); + +// Escapes a partial or complete file/pathname. This includes: +// non-printable, non-7bit, and (including space) "#%:<>?[\]^`{|} +BASE_EXPORT std::string EscapePath(StringPiece path); + +#if BUILDFLAG(IS_APPLE) +// Escapes characters as per expectations of NSURL. This includes: +// non-printable, non-7bit, and (including space) "#%<>[\]^`{|} +BASE_EXPORT std::string EscapeNSURLPrecursor(StringPiece precursor); +#endif // BUILDFLAG(IS_APPLE) + +// Escapes application/x-www-form-urlencoded content. This includes: +// non-printable, non-7bit, and (including space) ?>=<;+'&%$#"![\]^`{|} +// Space is escaped as + (if use_plus is true) and other special characters +// as %XX (hex). +BASE_EXPORT std::string EscapeUrlEncodedData(StringPiece path, bool use_plus); + +// Escapes all non-ASCII input, as well as escaping % to %25. +BASE_EXPORT std::string EscapeNonASCIIAndPercent(StringPiece input); + +// Escapes all non-ASCII input. Note this function leaves % unescaped, which +// means the unescaping the resulting string will not give back the original +// input. +BASE_EXPORT std::string EscapeNonASCII(StringPiece input); + +// Escapes characters in text suitable for use as an external protocol handler +// command. +// We %XX everything except alphanumerics and -_.!~*'() and the restricted +// characters (;/?:@&=+$,#[]) and a valid percent escape sequence (%XX). +BASE_EXPORT std::string EscapeExternalHandlerValue(StringPiece text); + +// Appends the given character to the output string, escaping the character if +// the character would be interpreted as an HTML delimiter. +BASE_EXPORT void AppendEscapedCharForHTML(char c, std::string* output); + +// Escapes chars that might cause this text to be interpreted as HTML tags. +BASE_EXPORT std::string EscapeForHTML(StringPiece text); +BASE_EXPORT std::u16string EscapeForHTML(StringPiece16 text); + +// Unescaping ------------------------------------------------------------------ + class UnescapeRule { public: // A combination of the following flags that is passed to the unescaping @@ -115,6 +167,10 @@ BASE_EXPORT bool ContainsEncodedBytes(StringPiece escaped_text, const std::set<unsigned char>& bytes); +// Unescapes the following ampersand character codes from |text|: +// < > & " ' +BASE_EXPORT std::u16string UnescapeForHTML(StringPiece16 text); + } // namespace base #endif // BASE_STRINGS_ESCAPE_H_
diff --git a/base/strings/escape_unittest.cc b/base/strings/escape_unittest.cc index 923eb5a..182e83f 100644 --- a/base/strings/escape_unittest.cc +++ b/base/strings/escape_unittest.cc
@@ -8,10 +8,22 @@ #include "base/strings/escape.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" namespace gurl_base { +namespace { + +struct EscapeCase { + const char* input; + const char* output; +}; + +struct EscapeForHTMLCase { + const char* input; + const char* expected_output; +}; struct UnescapeURLCase { const char* input; @@ -38,6 +50,155 @@ size_t output_offset; }; +TEST(EscapeTest, EscapeTextForFormSubmission) { + const EscapeCase escape_cases[] = { + {"foo", "foo"}, {"foo bar", "foo+bar"}, {"foo++", "foo%2B%2B"}}; + for (const auto& escape_case : escape_cases) { + EXPECT_EQ(escape_case.output, + EscapeQueryParamValue(escape_case.input, true)); + } + + const EscapeCase escape_cases_no_plus[] = { + {"foo", "foo"}, {"foo bar", "foo%20bar"}, {"foo++", "foo%2B%2B"}}; + for (const auto& escape_case : escape_cases_no_plus) { + EXPECT_EQ(escape_case.output, + EscapeQueryParamValue(escape_case.input, false)); + } + + // Test all the values in we're supposed to be escaping. + const std::string no_escape( + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "!'()*-._~"); + for (int i = 0; i < 256; ++i) { + std::string in; + in.push_back(i); + std::string out = EscapeQueryParamValue(in, true); + if (0 == i) { + EXPECT_EQ(out, std::string("%00")); + } else if (32 == i) { + // Spaces are plus escaped like web forms. + EXPECT_EQ(out, std::string("+")); + } else if (no_escape.find(in) == std::string::npos) { + // Check %hex escaping + std::string expected = StringPrintf("%%%02X", i); + EXPECT_EQ(expected, out); + } else { + // No change for things in the no_escape list. + EXPECT_EQ(out, in); + } + } +} + +TEST(EscapeTest, EscapePath) { + ASSERT_EQ( + // Most of the character space we care about, un-escaped + EscapePath("\x02\n\x1d !\"#$%&'()*+,-./0123456789:;" + "<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "[\\]^_`abcdefghijklmnopqrstuvwxyz" + "{|}~\x7f\x80\xff"), + // Escaped + "%02%0A%1D%20!%22%23$%25&'()*+,-./0123456789%3A;" + "%3C=%3E%3F@ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz" + "%7B%7C%7D~%7F%80%FF"); +} + +TEST(EscapeTest, EscapeUrlEncodedData) { + ASSERT_EQ( + // Most of the character space we care about, un-escaped + EscapeUrlEncodedData("\x02\n\x1d !\"#$%&'()*+,-./0123456789:;" + "<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "[\\]^_`abcdefghijklmnopqrstuvwxyz" + "{|}~\x7f\x80\xff", + true), + // Escaped + "%02%0A%1D+!%22%23%24%25%26%27()*%2B,-./0123456789:%3B" + "%3C%3D%3E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "%5B%5C%5D%5E_%60abcdefghijklmnopqrstuvwxyz" + "%7B%7C%7D~%7F%80%FF"); +} + +TEST(EscapeTest, EscapeUrlEncodedDataSpace) { + ASSERT_EQ(EscapeUrlEncodedData("a b", true), "a+b"); + ASSERT_EQ(EscapeUrlEncodedData("a b", false), "a%20b"); +} + +TEST(EscapeTest, EscapeForHTML) { + const EscapeForHTMLCase tests[] = { + {"hello", "hello"}, + {"<hello>", "<hello>"}, + {"don\'t mess with me", "don't mess with me"}, + }; + for (const auto& test : tests) { + std::string result = EscapeForHTML(std::string(test.input)); + EXPECT_EQ(std::string(test.expected_output), result); + } +} + +TEST(EscapeTest, UnescapeForHTML) { + const EscapeForHTMLCase tests[] = { + {"", ""}, + {"<hello>", "<hello>"}, + {"don't mess with me", "don\'t mess with me"}, + {"<>&"'", "<>&\"'"}, + {"& lt; & ; &; '", "& lt; & ; &; '"}, + {"&", "&"}, + {""", "\""}, + {"'", "'"}, + {"<", "<"}, + {">", ">"}, + {"& &", "& &"}, + }; + for (const auto& test : tests) { + std::u16string result = UnescapeForHTML(ASCIIToUTF16(test.input)); + EXPECT_EQ(ASCIIToUTF16(test.expected_output), result); + } +} + +TEST(EscapeTest, EscapeExternalHandlerValue) { + ASSERT_EQ( + // Escaped + "%02%0A%1D%20!%22#$%25&'()*+,-./0123456789:;" + "%3C=%3E?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "[%5C]%5E_%60abcdefghijklmnopqrstuvwxyz" + "%7B%7C%7D~%7F%80%FF", + // Most of the character space we care about, un-escaped + EscapeExternalHandlerValue("\x02\n\x1d !\"#$%&'()*+,-./0123456789:;" + "<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "[\\]^_`abcdefghijklmnopqrstuvwxyz" + "{|}~\x7f\x80\xff")); + + ASSERT_EQ( + "!#$&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_" + "abcdefghijklmnopqrstuvwxyz~", + EscapeExternalHandlerValue( + "!#$&'()*+,-./0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]_" + "abcdefghijklmnopqrstuvwxyz~")); + + ASSERT_EQ("%258k", EscapeExternalHandlerValue("%8k")); + ASSERT_EQ("a%25", EscapeExternalHandlerValue("a%")); + ASSERT_EQ("%25a", EscapeExternalHandlerValue("%a")); + ASSERT_EQ("a%258", EscapeExternalHandlerValue("a%8")); + ASSERT_EQ("%ab", EscapeExternalHandlerValue("%ab")); + ASSERT_EQ("%AB", EscapeExternalHandlerValue("%AB")); + + ASSERT_EQ("http://example.com/path/sub?q=a%7Cb%7Cc&q=1%7C2%7C3#ref%7C", + EscapeExternalHandlerValue( + "http://example.com/path/sub?q=a|b|c&q=1|2|3#ref|")); + ASSERT_EQ("http://example.com/path/sub?q=a%7Cb%7Cc&q=1%7C2%7C3#ref%7C", + EscapeExternalHandlerValue( + "http://example.com/path/sub?q=a%7Cb%7Cc&q=1%7C2%7C3#ref%7C")); + ASSERT_EQ("http://[2001:db8:0:1]:80", + EscapeExternalHandlerValue("http://[2001:db8:0:1]:80")); +} + +TEST(EscapeTest, EscapeNonASCII) { + EXPECT_EQ("abc\n%2580%80", EscapeNonASCIIAndPercent("abc\n%80\x80")); + EXPECT_EQ("abc\n%80%80", EscapeNonASCII("abc\n%80\x80")); +} + TEST(EscapeTest, DataURLWithAccentedCharacters) { const std::string url = "text/html;charset=utf-8,%3Chtml%3E%3Cbody%3ETonton,%20ton%20th%C3" @@ -427,4 +588,5 @@ ContainsEncodedBytes("caf%C3%A9", {static_cast<uint8_t>('\xe9')})); } +} // namespace } // namespace base
diff --git a/base/strings/string_number_conversions_internal.h b/base/strings/string_number_conversions_internal.h index 8c45d1b..6de9e2e 100644 --- a/base/strings/string_number_conversions_internal.h +++ b/base/strings/string_number_conversions_internal.h
@@ -12,7 +12,7 @@ #include <limits> -#include "polyfills/base/check_op.h" +#include "polyfills/base/check.h" #include "polyfills/base/logging.h" #include "base/numerics/safe_math.h" #include "base/strings/string_util.h"
diff --git a/base/strings/string_number_conversions_unittest.cc b/base/strings/string_number_conversions_unittest.cc index b5a23a1..34f811e 100644 --- a/base/strings/string_number_conversions_unittest.cc +++ b/base/strings/string_number_conversions_unittest.cc
@@ -14,7 +14,6 @@ #include <limits> #include "base/bit_cast.h" -#include "base/cxx17_backports.h" #include "base/format_macros.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -154,8 +153,10 @@ // One additional test to verify that conversion of numbers in strings with // embedded NUL characters. The NUL and extra data after it should be // interpreted as junk after the number. - const char input[] = "6\06"; - std::string input_string(input, gurl_base::size(input) - 1); + const char input[] = + "6\0" + "6"; + std::string input_string(input, std::size(input) - 1); int output; EXPECT_FALSE(StringToInt(input_string, &output)); EXPECT_EQ(6, output); @@ -220,8 +221,10 @@ // One additional test to verify that conversion of numbers in strings with // embedded NUL characters. The NUL and extra data after it should be // interpreted as junk after the number. - const char input[] = "6\06"; - std::string input_string(input, gurl_base::size(input) - 1); + const char input[] = + "6\0" + "6"; + std::string input_string(input, std::size(input) - 1); unsigned output; EXPECT_FALSE(StringToUint(input_string, &output)); EXPECT_EQ(6U, output); @@ -290,8 +293,10 @@ // One additional test to verify that conversion of numbers in strings with // embedded NUL characters. The NUL and extra data after it should be // interpreted as junk after the number. - const char input[] = "6\06"; - std::string input_string(input, gurl_base::size(input) - 1); + const char input[] = + "6\0" + "6"; + std::string input_string(input, std::size(input) - 1); int64_t output; EXPECT_FALSE(StringToInt64(input_string, &output)); EXPECT_EQ(6, output); @@ -357,8 +362,10 @@ // One additional test to verify that conversion of numbers in strings with // embedded NUL characters. The NUL and extra data after it should be // interpreted as junk after the number. - const char input[] = "6\06"; - std::string input_string(input, gurl_base::size(input) - 1); + const char input[] = + "6\0" + "6"; + std::string input_string(input, std::size(input) - 1); uint64_t output; EXPECT_FALSE(StringToUint64(input_string, &output)); EXPECT_EQ(6U, output); @@ -426,8 +433,10 @@ // One additional test to verify that conversion of numbers in strings with // embedded NUL characters. The NUL and extra data after it should be // interpreted as junk after the number. - const char input[] = "6\06"; - std::string input_string(input, gurl_base::size(input) - 1); + const char input[] = + "6\0" + "6"; + std::string input_string(input, std::size(input) - 1); size_t output; EXPECT_FALSE(StringToSizeT(input_string, &output)); EXPECT_EQ(6U, output); @@ -486,7 +495,7 @@ const char input[] = "0xc0ffee\0" "9"; - std::string input_string(input, gurl_base::size(input) - 1); + std::string input_string(input, std::size(input) - 1); int output; EXPECT_FALSE(HexStringToInt(input_string, &output)); EXPECT_EQ(0xc0ffee, output); @@ -553,7 +562,7 @@ const char input[] = "0xc0ffee\0" "9"; - std::string input_string(input, gurl_base::size(input) - 1); + std::string input_string(input, std::size(input) - 1); uint32_t output; EXPECT_FALSE(HexStringToUInt(input_string, &output)); EXPECT_EQ(0xc0ffeeU, output); @@ -614,7 +623,7 @@ const char input[] = "0xc0ffee\0" "9"; - std::string input_string(input, gurl_base::size(input) - 1); + std::string input_string(input, std::size(input) - 1); int64_t output; EXPECT_FALSE(HexStringToInt64(input_string, &output)); EXPECT_EQ(0xc0ffee, output); @@ -679,7 +688,7 @@ const char input[] = "0xc0ffee\0" "9"; - std::string input_string(input, gurl_base::size(input) - 1); + std::string input_string(input, std::size(input) - 1); uint64_t output; EXPECT_FALSE(HexStringToUInt64(input_string, &output)); EXPECT_EQ(0xc0ffeeU, output); @@ -712,7 +721,7 @@ 11, true}, }; - for (size_t test_i = 0; test_i < gurl_base::size(cases); ++test_i) { + for (size_t test_i = 0; test_i < std::size(cases); ++test_i) { const auto& test = cases[test_i]; std::string expected_output(test.output, test.output_len); @@ -855,7 +864,7 @@ -1.0000000000000001e-259, true}, }; - for (size_t i = 0; i < gurl_base::size(cases); ++i) { + for (size_t i = 0; i < std::size(cases); ++i) { SCOPED_TRACE( StringPrintf("case %" PRIuS " \"%s\"", i, cases[i].input.c_str())); double output; @@ -872,7 +881,7 @@ const char input[] = "3.14\0" "159"; - std::string input_string(input, gurl_base::size(input) - 1); + std::string input_string(input, std::size(input) - 1); double output; EXPECT_FALSE(StringToDouble(input_string, &output)); EXPECT_DOUBLE_EQ(3.14, output); @@ -901,12 +910,12 @@ // The following two values were seen in crashes in the wild. const char input_bytes[8] = {0, 0, 0, 0, '\xee', '\x6d', '\x73', '\x42'}; double input = 0; - memcpy(&input, input_bytes, gurl_base::size(input_bytes)); + memcpy(&input, input_bytes, std::size(input_bytes)); EXPECT_EQ("1.335179083776e+12", NumberToString(input)); const char input_bytes2[8] = {0, 0, 0, '\xa0', '\xda', '\x6c', '\x73', '\x42'}; input = 0; - memcpy(&input, input_bytes2, gurl_base::size(input_bytes2)); + memcpy(&input, input_bytes2, std::size(input_bytes2)); EXPECT_EQ("1.33489033216e+12", NumberToString(input)); }
diff --git a/base/strings/string_piece.h b/base/strings/string_piece.h index 8d7f2c5..21ee624 100644 --- a/base/strings/string_piece.h +++ b/base/strings/string_piece.h
@@ -30,9 +30,9 @@ #include <type_traits> #include "polyfills/base/base_export.h" +#include "polyfills/base/check.h" #include "polyfills/base/check_op.h" #include "base/compiler_specific.h" -#include "base/strings/char_traits.h" #include "base/strings/string_piece_forward.h" #include "build/build_config.h" @@ -118,10 +118,8 @@ default; constexpr BasicStringPiece(const CharT* s, size_type count) : ptr_(s), length_(count) {} - // Note: This doesn't just use traits_type::length(), since that - // isn't constexpr until C++17. constexpr BasicStringPiece(const CharT* s) - : ptr_(s), length_(s ? CharTraits<CharT>::length(s) : 0) { + : ptr_(s), length_(s ? traits_type::length(s) : 0) { // Intentional STL deviation: Null-check instead of UB. GURL_CHECK(s); } @@ -229,7 +227,7 @@ constexpr int compare(BasicStringPiece v) const noexcept { const size_type rlen = std::min(size(), v.size()); - const int result = CharTraits<CharT>::compare(data(), v.data(), rlen); + const int result = traits_type::compare(data(), v.data(), rlen); if (result != 0) return result; if (size() == v.size()) @@ -282,7 +280,7 @@ return npos; const const_pointer result = - gurl_base::CharTraits<CharT>::find(data() + pos, size() - pos, ch); + traits_type::find(data() + pos, size() - pos, ch); return result ? static_cast<size_type>(result - data()) : npos; } constexpr size_type find(const CharT* s,
diff --git a/base/strings/string_tokenizer.h b/base/strings/string_tokenizer.h index 14db1e1..e85bf45 100644 --- a/base/strings/string_tokenizer.h +++ b/base/strings/string_tokenizer.h
@@ -8,6 +8,7 @@ #include <algorithm> #include <string> +#include "polyfills/base/check.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h"
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc index 2adfa94..937c603 100644 --- a/base/strings/string_util.cc +++ b/base/strings/string_util.cc
@@ -22,7 +22,6 @@ #include <vector> #include "polyfills/base/check_op.h" -#include "base/cxx17_backports.h" #include "base/no_destructor.h" #include "base/strings/string_util_internal.h" #include "base/strings/utf_string_conversion_utils.h" @@ -336,17 +335,17 @@ size_t dimension = 0; const int kKilo = 1024; while (unit_amount >= kKilo && - dimension < gurl_base::size(kByteStringsUnlocalized) - 1) { + dimension < std::size(kByteStringsUnlocalized) - 1) { unit_amount /= kKilo; dimension++; } char buf[64]; if (bytes != 0 && dimension > 0 && unit_amount < 100) { - gurl_base::snprintf(buf, gurl_base::size(buf), "%.1lf%s", unit_amount, + gurl_base::snprintf(buf, std::size(buf), "%.1lf%s", unit_amount, kByteStringsUnlocalized[dimension]); } else { - gurl_base::snprintf(buf, gurl_base::size(buf), "%.0lf%s", unit_amount, + gurl_base::snprintf(buf, std::size(buf), "%.0lf%s", unit_amount, kByteStringsUnlocalized[dimension]); }
diff --git a/base/strings/string_util.h b/base/strings/string_util.h index 5d570e2..cd90a94 100644 --- a/base/strings/string_util.h +++ b/base/strings/string_util.h
@@ -18,6 +18,7 @@ #include <vector> #include "polyfills/base/base_export.h" +#include "polyfills/base/check_op.h" #include "base/compiler_specific.h" #include "base/containers/span.h" #include "base/cxx20_to_address.h"
diff --git a/base/strings/string_util_internal.h b/base/strings/string_util_internal.h index 07f4930..2497c8d 100644 --- a/base/strings/string_util_internal.h +++ b/base/strings/string_util_internal.h
@@ -7,6 +7,8 @@ #include <algorithm> +#include "polyfills/base/check.h" +#include "polyfills/base/check_op.h" #include "polyfills/base/logging.h" #include "polyfills/base/notreached.h" #include "base/ranges/algorithm.h" @@ -523,7 +525,7 @@ typename T, typename CharT = typename T::value_type> static std::basic_string<CharT> JoinStringT(list_type parts, T sep) { - if (gurl_base::empty(parts)) + if (std::empty(parts)) return std::basic_string<CharT>(); // Pre-allocate the eventual size of the string. Start with the size of all of
diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc index 231c3c8..b5d9a67 100644 --- a/base/strings/string_util_unittest.cc +++ b/base/strings/string_util_unittest.cc
@@ -14,7 +14,6 @@ #include <type_traits> #include "base/bits.h" -#include "base/cxx17_backports.h" #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" @@ -218,14 +217,14 @@ { const char array[] = "\x00\x00\xc2\x81\xc2\x81"; - const std::string array_string(array, gurl_base::size(array)); + const std::string array_string(array, std::size(array)); EXPECT_TRUE(Truncated(array_string, 4, &output)); EXPECT_EQ(output.compare(std::string("\x00\x00\xc2\x81", 4)), 0); } { const char array[] = "\x00\xc2\x81\xc2\x81"; - const std::string array_string(array, gurl_base::size(array)); + const std::string array_string(array, std::size(array)); EXPECT_TRUE(Truncated(array_string, 4, &output)); EXPECT_EQ(output.compare(std::string("\x00\xc2\x81", 3)), 0); } @@ -292,7 +291,7 @@ { const char array[] = "\x00\x00\xfe\xff"; - const std::string array_string(array, gurl_base::size(array)); + const std::string array_string(array, std::size(array)); EXPECT_TRUE(Truncated(array_string, 4, &output)); EXPECT_EQ(output.compare(std::string("\x00\x00", 2)), 0); } @@ -306,7 +305,7 @@ } { const char array[] = "\xff\x00\x00\xfe"; - const std::string array_string(array, gurl_base::size(array)); + const std::string array_string(array, std::size(array)); EXPECT_TRUE(Truncated(array_string, 4, &output)); EXPECT_EQ(output.compare(std::string("\xff\x00\x00", 3)), 0); } @@ -536,7 +535,7 @@ // Also, test that a non-ASCII character will be detected regardless of its // position inside the string. { - const size_t string_length = gurl_base::size(char_ascii) - 1; + const size_t string_length = std::size(char_ascii) - 1; for (size_t offset = 0; offset < 8; ++offset) { for (size_t len = 0, max_len = string_length - offset; len < max_len; ++len) { @@ -551,7 +550,7 @@ } { - const size_t string_length = gurl_base::size(char16_ascii) - 1; + const size_t string_length = std::size(char16_ascii) - 1; for (size_t offset = 0; offset < 4; ++offset) { for (size_t len = 0, max_len = string_length - offset; len < max_len; ++len) { @@ -605,7 +604,7 @@ L"0123ABCDwxyz \a\b\t\r\n!+,.~" }; - for (size_t i = 0; i < gurl_base::size(char_cases); ++i) { + for (size_t i = 0; i < std::size(char_cases); ++i) { EXPECT_TRUE(IsStringASCII(char_cases[i])); std::u16string utf16 = ASCIIToUTF16(char_cases[i]); EXPECT_EQ(WideToUTF16(wchar_cases[i]), utf16); @@ -624,7 +623,7 @@ // Convert strings with an embedded NUL character. const char chars_with_nul[] = "test\0string"; - const int length_with_nul = gurl_base::size(chars_with_nul) - 1; + const int length_with_nul = std::size(chars_with_nul) - 1; std::string string_with_nul(chars_with_nul, length_with_nul); std::u16string string16_with_nul = ASCIIToUTF16(string_with_nul); EXPECT_EQ(static_cast<std::u16string::size_type>(length_with_nul), @@ -1219,9 +1218,9 @@ { char dst[10]; wchar_t wdst[10]; - EXPECT_EQ(7U, strlcpy(dst, "abcdefg", gurl_base::size(dst))); + EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst))); EXPECT_EQ(0, memcmp(dst, "abcdefg", 8)); - EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", gurl_base::size(wdst))); + EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst))); EXPECT_EQ(0, memcmp(wdst, L"abcdefg", sizeof(wchar_t) * 8)); } @@ -1242,9 +1241,9 @@ { char dst[8]; wchar_t wdst[8]; - EXPECT_EQ(7U, strlcpy(dst, "abcdefg", gurl_base::size(dst))); + EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst))); EXPECT_EQ(0, memcmp(dst, "abcdefg", 8)); - EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", gurl_base::size(wdst))); + EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst))); EXPECT_EQ(0, memcmp(wdst, L"abcdefg", sizeof(wchar_t) * 8)); } @@ -1252,9 +1251,9 @@ { char dst[7]; wchar_t wdst[7]; - EXPECT_EQ(7U, strlcpy(dst, "abcdefg", gurl_base::size(dst))); + EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst))); EXPECT_EQ(0, memcmp(dst, "abcdef", 7)); - EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", gurl_base::size(wdst))); + EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst))); EXPECT_EQ(0, memcmp(wdst, L"abcdef", sizeof(wchar_t) * 7)); } @@ -1262,9 +1261,9 @@ { char dst[3]; wchar_t wdst[3]; - EXPECT_EQ(7U, strlcpy(dst, "abcdefg", gurl_base::size(dst))); + EXPECT_EQ(7U, strlcpy(dst, "abcdefg", std::size(dst))); EXPECT_EQ(0, memcmp(dst, "ab", 3)); - EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", gurl_base::size(wdst))); + EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", std::size(wdst))); EXPECT_EQ(0, memcmp(wdst, L"ab", sizeof(wchar_t) * 3)); } } @@ -1504,7 +1503,7 @@ // Using std::string(buffer.c_str()) instead of |buffer| truncates the // string at the first \0. EXPECT_EQ( - std::string(kOriginal, std::min(num_chars, gurl_base::size(kOriginal) - 1)), + std::string(kOriginal, std::min(num_chars, std::size(kOriginal) - 1)), std::string(buffer.c_str())); EXPECT_EQ(num_chars, buffer.size()); }
diff --git a/base/strings/stringprintf.cc b/base/strings/stringprintf.cc index aed9b04..e0c5e20 100644 --- a/base/strings/stringprintf.cc +++ b/base/strings/stringprintf.cc
@@ -9,11 +9,9 @@ #include <vector> -#include "base/cxx17_backports.h" #include "polyfills/base/logging.h" #include "base/scoped_clear_last_error.h" #include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" #include "build/build_config.h" namespace gurl_base { @@ -64,17 +62,17 @@ va_copy(ap_copy, ap); gurl_base::ScopedClearLastError last_error; - int result = vsnprintfT(stack_buf, gurl_base::size(stack_buf), format, ap_copy); + int result = vsnprintfT(stack_buf, std::size(stack_buf), format, ap_copy); va_end(ap_copy); - if (result >= 0 && result < static_cast<int>(gurl_base::size(stack_buf))) { + if (result >= 0 && result < static_cast<int>(std::size(stack_buf))) { // It fit. dst->append(stack_buf, result); return; } // Repeatedly increase buffer size until it fits. - int mem_length = gurl_base::size(stack_buf); + int mem_length = std::size(stack_buf); while (true) { if (result < 0) { #if BUILDFLAG(IS_WIN)
diff --git a/base/strings/utf_offset_string_conversions_unittest.cc b/base/strings/utf_offset_string_conversions_unittest.cc index f50fa3f..83bbc35 100644 --- a/base/strings/utf_offset_string_conversions_unittest.cc +++ b/base/strings/utf_offset_string_conversions_unittest.cc
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/strings/utf_offset_string_conversions.h" + #include <stddef.h> #include <algorithm> -#include "base/cxx17_backports.h" #include "base/strings/string_piece.h" -#include "base/strings/utf_offset_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" namespace gurl_base { @@ -66,7 +66,7 @@ {{'A', 0xd800, 0xdf00, 'z'}, 3, 5}, {{'A', 0xd800, 0xdf00, 'z'}, 4, 6}, }; - for (size_t i = 0; i < gurl_base::size(utf16_to_utf8_cases); ++i) { + for (size_t i = 0; i < std::size(utf16_to_utf8_cases); ++i) { size_t offset = utf16_to_utf8_cases[i].input_offset; std::vector<size_t> offsets; offsets.push_back(offset); @@ -117,8 +117,8 @@ adjustments.push_back(OffsetAdjuster::Adjustment(3, 3, 1)); OffsetAdjuster::AdjustOffsets(adjustments, &offsets); size_t expected_1[] = {0, 1, 2, 3, kNpos, kNpos, 4, 5, 6, 7}; - EXPECT_EQ(offsets.size(), gurl_base::size(expected_1)); - for (size_t i = 0; i < gurl_base::size(expected_1); ++i) + EXPECT_EQ(offsets.size(), std::size(expected_1)); + for (size_t i = 0; i < std::size(expected_1); ++i) EXPECT_EQ(expected_1[i], offsets[i]); } @@ -137,8 +137,8 @@ 0, kNpos, kNpos, 1, 2, kNpos, kNpos, kNpos, 4, 5, 6, kNpos, kNpos, kNpos, kNpos, kNpos, kNpos, 10, 11, 12, 13, kNpos, kNpos, 14 }; - EXPECT_EQ(offsets.size(), gurl_base::size(expected_2)); - for (size_t i = 0; i < gurl_base::size(expected_2); ++i) + EXPECT_EQ(offsets.size(), std::size(expected_2)); + for (size_t i = 0; i < std::size(expected_2); ++i) EXPECT_EQ(expected_2[i], offsets[i]); } @@ -157,8 +157,8 @@ 0, kNpos, kNpos, 0, 1, kNpos, kNpos, kNpos, 5, 6, 7, 8, kNpos, kNpos, 11, 12, kNpos, 12 }; - EXPECT_EQ(offsets.size(), gurl_base::size(expected_3)); - for (size_t i = 0; i < gurl_base::size(expected_3); ++i) + EXPECT_EQ(offsets.size(), std::size(expected_3)); + for (size_t i = 0; i < std::size(expected_3); ++i) EXPECT_EQ(expected_3[i], offsets[i]); } } @@ -175,8 +175,8 @@ adjustments.push_back(OffsetAdjuster::Adjustment(3, 3, 1)); OffsetAdjuster::UnadjustOffsets(adjustments, &offsets); size_t expected_1[] = {0, 1, 2, 3, 6, 7, 8, 9}; - EXPECT_EQ(offsets.size(), gurl_base::size(expected_1)); - for (size_t i = 0; i < gurl_base::size(expected_1); ++i) + EXPECT_EQ(offsets.size(), std::size(expected_1)); + for (size_t i = 0; i < std::size(expected_1); ++i) EXPECT_EQ(expected_1[i], offsets[i]); } @@ -194,8 +194,8 @@ size_t expected_2[] = { 0, 3, 4, kNpos, 8, 9, 10, kNpos, kNpos, kNpos, 17, 18, 19, 20, 23 }; - EXPECT_EQ(offsets.size(), gurl_base::size(expected_2)); - for (size_t i = 0; i < gurl_base::size(expected_2); ++i) + EXPECT_EQ(offsets.size(), std::size(expected_2)); + for (size_t i = 0; i < std::size(expected_2); ++i) EXPECT_EQ(expected_2[i], offsets[i]); } @@ -215,8 +215,8 @@ 4, kNpos, kNpos, kNpos, 8, 9, 10, 11, kNpos, kNpos, 14, 15 // this could just as easily be 17 }; - EXPECT_EQ(offsets.size(), gurl_base::size(expected_3)); - for (size_t i = 0; i < gurl_base::size(expected_3); ++i) + EXPECT_EQ(offsets.size(), std::size(expected_3)); + for (size_t i = 0; i < std::size(expected_3); ++i) EXPECT_EQ(expected_3[i], offsets[i]); } }
diff --git a/base/strings/utf_string_conversions_unittest.cc b/base/strings/utf_string_conversions_unittest.cc index 3b26fa8..f738da4 100644 --- a/base/strings/utf_string_conversions_unittest.cc +++ b/base/strings/utf_string_conversions_unittest.cc
@@ -2,12 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/strings/utf_string_conversions.h" + #include <stddef.h> -#include "base/cxx17_backports.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -189,14 +189,14 @@ '\0' }; std::u16string multistring16; - memcpy(WriteInto(&multistring16, gurl_base::size(multi16)), multi16, + memcpy(WriteInto(&multistring16, std::size(multi16)), multi16, sizeof(multi16)); - EXPECT_EQ(gurl_base::size(multi16) - 1, multistring16.length()); + EXPECT_EQ(std::size(multi16) - 1, multistring16.length()); std::string expected; - memcpy(WriteInto(&expected, gurl_base::size(multi)), multi, sizeof(multi)); - EXPECT_EQ(gurl_base::size(multi) - 1, expected.length()); + memcpy(WriteInto(&expected, std::size(multi)), multi, sizeof(multi)); + EXPECT_EQ(std::size(multi) - 1, expected.length()); const std::string& converted = UTF16ToUTF8(multistring16); - EXPECT_EQ(gurl_base::size(multi) - 1, converted.length()); + EXPECT_EQ(std::size(multi) - 1, converted.length()); EXPECT_EQ(expected, converted); }
diff --git a/base/template_util.h b/base/template_util.h index 3d954fd..c00791b 100644 --- a/base/template_util.h +++ b/base/template_util.h
@@ -13,32 +13,6 @@ #include "base/compiler_specific.h" -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 7 -#include <vector> -#endif - -// Some versions of libstdc++ have partial support for type_traits, but misses -// a smaller subset while removing some of the older non-standard stuff. Assume -// that all versions below 5.0 fall in this category, along with one 5.0 -// experimental release. Test for this by consulting compiler major version, -// the only reliable option available, so theoretically this could fail should -// you attempt to mix an earlier version of libstdc++ with >= GCC5. But -// that's unlikely to work out, especially as GCC5 changed ABI. -#define CR_GLIBCXX_5_0_0 20150123 -#if (defined(__GNUC__) && __GNUC__ < 5) || \ - (defined(__GLIBCXX__) && __GLIBCXX__ == CR_GLIBCXX_5_0_0) -#define CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX -#endif - -// This hacks around using gcc with libc++ which has some incompatibilies. -// - is_trivially_* doesn't work: https://llvm.org/bugs/show_bug.cgi?id=27538 -// TODO(danakj): Remove this when android builders are all using a newer version -// of gcc, or the android ndk is updated to a newer libc++ that works with older -// gcc versions. -#if !defined(__clang__) && defined(_LIBCPP_VERSION) -#define CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX -#endif - namespace gurl_base { template <class T> struct is_non_const_reference : std::false_type {}; @@ -47,25 +21,6 @@ namespace internal { -// Implementation detail of gurl_base::void_t below. -template <typename...> -struct make_void { - using type = void; -}; - -} // namespace internal - -// gurl_base::void_t is an implementation of std::void_t from C++17. -// -// We use |gurl_base::internal::make_void| as a helper struct to avoid a C++14 -// defect: -// http://en.cppreference.com/w/cpp/types/void_t -// http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#1558 -template <typename... Ts> -using void_t = typename ::gurl_base::internal::make_void<Ts...>::type; - -namespace internal { - // Uses expression SFINAE to detect whether using operator<< would work. template <typename T, typename = void> struct SupportsOstreamOperator : std::false_type {}; @@ -88,8 +43,9 @@ struct is_iterator : std::false_type {}; template <typename T> -struct is_iterator<T, - void_t<typename std::iterator_traits<T>::iterator_category>> +struct is_iterator< + T, + std::void_t<typename std::iterator_traits<T>::iterator_category>> : std::true_type {}; // Helper to express preferences in an overload set. If more than one overload @@ -103,67 +59,6 @@ } // namespace internal -// is_trivially_copyable is especially hard to get right. -// - Older versions of libstdc++ will fail to have it like they do for other -// type traits. This has become a subset of the second point, but used to be -// handled independently. -// - An experimental release of gcc includes most of type_traits but misses -// is_trivially_copyable, so we still have to avoid using libstdc++ in this -// case, which is covered by CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX. -// - When compiling libc++ from before r239653, with a gcc compiler, the -// std::is_trivially_copyable can fail. So we need to work around that by not -// using the one in libc++ in this case. This is covered by the -// CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX define, and is discussed in -// https://llvm.org/bugs/show_bug.cgi?id=27538#c1 where they point out that -// in libc++'s commit r239653 this is fixed by libc++ checking for gcc 5.1. -// - In both of the above cases we are using the gcc compiler. When defining -// this ourselves on compiler intrinsics, the __is_trivially_copyable() -// intrinsic is not available on gcc before version 5.1 (see the discussion in -// https://llvm.org/bugs/show_bug.cgi?id=27538#c1 again), so we must check for -// that version. -// - When __is_trivially_copyable() is not available because we are on gcc older -// than 5.1, we need to fall back to something, so we use __has_trivial_copy() -// instead based on what was done one-off in bit_cast() previously. - -// TODO(crbug.com/554293): Remove this when all platforms have this in the std -// namespace and it works with gcc as needed. -#if defined(CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX) || \ - defined(CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX) -template <typename T> -struct is_trivially_copyable { -// TODO(danakj): Remove this when android builders are all using a newer version -// of gcc, or the android ndk is updated to a newer libc++ that does this for -// us. -#if _GNUC_VER >= 501 - static constexpr bool value = __is_trivially_copyable(T); -#else - static constexpr bool value = - __has_trivial_copy(T) && __has_trivial_destructor(T); -#endif -}; -#else -template <class T> -using is_trivially_copyable = std::is_trivially_copyable<T>; -#endif - -#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ <= 7 -// Workaround for g++7 and earlier family. -// Due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80654, without this -// absl::optional<std::vector<T>> where T is non-copyable causes a compile -// error. As we know it is not trivially copy constructible, explicitly declare -// so. -template <typename T> -struct is_trivially_copy_constructible - : std::is_trivially_copy_constructible<T> {}; - -template <typename... T> -struct is_trivially_copy_constructible<std::vector<T...>> : std::false_type {}; -#else -// Otherwise use std::is_trivially_copy_constructible as is. -template <typename T> -using is_trivially_copy_constructible = std::is_trivially_copy_constructible<T>; -#endif - // gurl_base::in_place_t is an implementation of std::in_place_t from // C++17. A tag type used to request in-place construction in template vararg // constructors. @@ -193,102 +88,6 @@ static constexpr bool value = true; }; -// C++14 implementation of C++17's std::bool_constant. -// -// Reference: https://en.cppreference.com/w/cpp/types/integral_constant -// Specification: https://wg21.link/meta.type.synop -template <bool B> -using bool_constant = std::integral_constant<bool, B>; - -// C++14 implementation of C++17's std::conjunction. -// -// Reference: https://en.cppreference.com/w/cpp/types/conjunction -// Specification: https://wg21.link/meta.logical#1.itemdecl:1 -template <typename...> -struct conjunction : std::true_type {}; - -template <typename B1> -struct conjunction<B1> : B1 {}; - -template <typename B1, typename... Bn> -struct conjunction<B1, Bn...> - : std::conditional_t<static_cast<bool>(B1::value), conjunction<Bn...>, B1> { -}; - -// C++14 implementation of C++17's std::disjunction. -// -// Reference: https://en.cppreference.com/w/cpp/types/disjunction -// Specification: https://wg21.link/meta.logical#itemdecl:2 -template <typename...> -struct disjunction : std::false_type {}; - -template <typename B1> -struct disjunction<B1> : B1 {}; - -template <typename B1, typename... Bn> -struct disjunction<B1, Bn...> - : std::conditional_t<static_cast<bool>(B1::value), B1, disjunction<Bn...>> { -}; - -// C++14 implementation of C++17's std::negation. -// -// Reference: https://en.cppreference.com/w/cpp/types/negation -// Specification: https://wg21.link/meta.logical#itemdecl:3 -template <typename B> -struct negation : bool_constant<!static_cast<bool>(B::value)> {}; - -// Implementation of C++17's invoke_result. -// -// This implementation adds references to `Functor` and `Args` to work around -// some quirks of std::result_of. See the #Notes section of [1] for details. -// -// References: -// [1] https://en.cppreference.com/w/cpp/types/result_of -// [2] https://wg21.link/meta.trans.other#lib:invoke_result -template <typename Functor, typename... Args> -using invoke_result = std::invoke_result<Functor, Args...>; - -// Implementation of C++17's std::invoke_result_t. -// -// Reference: https://wg21.link/meta.type.synop#lib:invoke_result_t -template <typename Functor, typename... Args> -using invoke_result_t = typename invoke_result<Functor, Args...>::type; - -namespace internal { - -// Base case, `InvokeResult` does not have a nested type member. This means `F` -// could not be invoked with `Args...` and thus is not invocable. -template <typename InvokeResult, typename R, typename = void> -struct IsInvocableImpl : std::false_type {}; - -// Happy case, `InvokeResult` does have a nested type member. Now check whether -// `InvokeResult::type` is convertible to `R`. Short circuit in case -// `std::is_void<R>`. -template <typename InvokeResult, typename R> -struct IsInvocableImpl<InvokeResult, R, void_t<typename InvokeResult::type>> - : disjunction<std::is_void<R>, - std::is_convertible<typename InvokeResult::type, R>> {}; - -} // namespace internal - -// Implementation of C++17's std::is_invocable_r. -// -// Returns whether `F` can be invoked with `Args...` and the result is -// convertible to `R`. -// -// Reference: https://wg21.link/meta.rel#lib:is_invocable_r -template <typename R, typename F, typename... Args> -struct is_invocable_r - : internal::IsInvocableImpl<invoke_result<F, Args...>, R> {}; - -// Implementation of C++17's std::is_invocable. -// -// Returns whether `F` can be invoked with `Args...`. -// -// Reference: https://wg21.link/meta.rel#lib:is_invocable -template <typename F, typename... Args> -struct is_invocable : is_invocable_r<void, F, Args...> {}; - namespace internal { // The indirection with std::is_enum<T> is required, because instantiating @@ -298,7 +97,7 @@ template <typename T> struct IsScopedEnumImpl<T, /*std::is_enum<T>::value=*/true> - : negation<std::is_convertible<T, std::underlying_type_t<T>>> {}; + : std::negation<std::is_convertible<T, std::underlying_type_t<T>>> {}; } // namespace internal @@ -363,7 +162,8 @@ // // Reference: https://wg21.link/iterator.synopsis#:~:text=indirect_result_t template <typename Func, typename... Iters> -using indirect_result_t = invoke_result_t<Func, iter_reference_t<Iters>...>; +using indirect_result_t = + std::invoke_result_t<Func, iter_reference_t<Iters>...>; // Simplified implementation of C++20's std::projected. As opposed to // std::projected, this implementation does not explicitly restrict the type of @@ -383,7 +183,4 @@ } // namespace base -#undef CR_USE_FALLBACKS_FOR_GCC_WITH_LIBCXX -#undef CR_USE_FALLBACKS_FOR_OLD_EXPERIMENTAL_GLIBCXX - #endif // BASE_TEMPLATE_UTIL_H_
diff --git a/copy.bara.sky b/copy.bara.sky index 44173d6..9741b8b 100644 --- a/copy.bara.sky +++ b/copy.bara.sky
@@ -103,6 +103,8 @@ core.replace("#include \"base/win/windows_types.h\"", "#include <windows.h>"), core.replace("#include \"base/strings/string_number_conversions_win.h\"", ""), + core.replace("#include \"base/allocator/partition_allocator/partition_alloc_config.h\"", ""), + core.replace("base/trace_event/base_tracing_forward.h", "polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h"), # Use system ICU. core.replace(
diff --git a/polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h b/polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h index b2f0286..6d059f7 100644 --- a/polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h +++ b/polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h
@@ -12,6 +12,15 @@ void WriteString(const std::string&) && {} }; +template <typename T> +void WriteIntoTracedValue(TracedValue context, T&& value) {} + +template <typename T, typename ResultType = void, class = void> +struct check_traced_value_support { + static constexpr bool value = true; + using type = ResultType; +}; + } // namespace perfetto #endif // POLYFILLS_THIRD_PARTY_PERFETTO_INCLUDE_PERFETTO_TRACING_TRACED_VALUE_H_
diff --git a/url/gurl.cc b/url/gurl.cc index 3dd0228..5c6b76c 100644 --- a/url/gurl.cc +++ b/url/gurl.cc
@@ -110,17 +110,17 @@ // removed from a "foo:hello #ref" URL (see http://crbug.com/291747). GURL test_url(spec_, RETAIN_TRAILING_PATH_WHITEPACE); - GURL_DCHECK(test_url.is_valid_ == is_valid_); - GURL_DCHECK(test_url.spec_ == spec_); + GURL_DCHECK_EQ(test_url.is_valid_, is_valid_); + GURL_DCHECK_EQ(test_url.spec_, spec_); - GURL_DCHECK(test_url.parsed_.scheme == parsed_.scheme); - GURL_DCHECK(test_url.parsed_.username == parsed_.username); - GURL_DCHECK(test_url.parsed_.password == parsed_.password); - GURL_DCHECK(test_url.parsed_.host == parsed_.host); - GURL_DCHECK(test_url.parsed_.port == parsed_.port); - GURL_DCHECK(test_url.parsed_.path == parsed_.path); - GURL_DCHECK(test_url.parsed_.query == parsed_.query); - GURL_DCHECK(test_url.parsed_.ref == parsed_.ref); + GURL_DCHECK_EQ(test_url.parsed_.scheme, parsed_.scheme); + GURL_DCHECK_EQ(test_url.parsed_.username, parsed_.username); + GURL_DCHECK_EQ(test_url.parsed_.password, parsed_.password); + GURL_DCHECK_EQ(test_url.parsed_.host, parsed_.host); + GURL_DCHECK_EQ(test_url.parsed_.port, parsed_.port); + GURL_DCHECK_EQ(test_url.parsed_.path, parsed_.path); + GURL_DCHECK_EQ(test_url.parsed_.query, parsed_.query); + GURL_DCHECK_EQ(test_url.parsed_.ref, parsed_.ref); } } #endif @@ -223,8 +223,7 @@ } // Note: code duplicated below (it's inconvenient to use a template here). -GURL GURL::ReplaceComponents( - const url::Replacements<char>& replacements) const { +GURL GURL::ReplaceComponents(const Replacements& replacements) const { GURL result; // Not allowed for invalid URLs. @@ -243,8 +242,7 @@ } // Note: code duplicated above (it's inconvenient to use a template here). -GURL GURL::ReplaceComponents( - const url::Replacements<char16_t>& replacements) const { +GURL GURL::ReplaceComponents(const ReplacementsW& replacements) const { GURL result; // Not allowed for invalid URLs. @@ -281,7 +279,7 @@ if (SchemeIsFileSystem()) return inner_url_->DeprecatedGetOriginAsURL(); - url::Replacements<char> replacements; + Replacements replacements; replacements.ClearUsername(); replacements.ClearPassword(); replacements.ClearPath(); @@ -298,7 +296,7 @@ if (!has_ref() && !has_username() && !has_password()) return GURL(*this); - url::Replacements<char> replacements; + Replacements replacements; replacements.ClearRef(); replacements.ClearUsername(); replacements.ClearPassword();
diff --git a/url/gurl.h b/url/gurl.h index ee009de..63729ee 100644 --- a/url/gurl.h +++ b/url/gurl.h
@@ -164,10 +164,10 @@ // It is an error to replace components of an invalid URL. The result will // be the empty URL. // - // Note that we use the more general url::Replacements type to give - // callers extra flexibility rather than our override. - GURL ReplaceComponents(const url::Replacements<char>& replacements) const; - GURL ReplaceComponents(const url::Replacements<char16_t>& replacements) const; + // Note that this intentionally disallows direct use of url::Replacements, + // which is harder to use correctly. + GURL ReplaceComponents(const Replacements& replacements) const; + GURL ReplaceComponents(const ReplacementsW& replacements) const; // A helper function that is equivalent to replacing the path with a slash // and clearing out everything after that. We sometimes need to know just the
diff --git a/url/gurl_unittest.cc b/url/gurl_unittest.cc index e793542..6dd1fc0 100644 --- a/url/gurl_unittest.cc +++ b/url/gurl_unittest.cc
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "url/gurl.h" + #include <stddef.h> -#include "base/cxx17_backports.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" #include "url/gurl_abstract_tests.h" #include "url/origin.h" #include "url/url_canon.h" @@ -222,7 +222,7 @@ "http:/path", "http:path", }; - for (size_t i = 0; i < gurl_base::size(valid_cases); i++) { + for (size_t i = 0; i < std::size(valid_cases); i++) { EXPECT_TRUE(GURL(valid_cases[i]).is_valid()) << "Case: " << valid_cases[i]; } @@ -237,7 +237,7 @@ "://google.com", "path", }; - for (size_t i = 0; i < gurl_base::size(invalid_cases); i++) { + for (size_t i = 0; i < std::size(invalid_cases); i++) { EXPECT_FALSE(GURL(invalid_cases[i]).is_valid()) << "Case: " << invalid_cases[i]; } @@ -346,7 +346,7 @@ {"file:///some/dir/", "://host", true, "file:///some/dir/://host"}, }; - for (size_t i = 0; i < gurl_base::size(resolve_cases); i++) { + for (size_t i = 0; i < std::size(resolve_cases); i++) { // 8-bit code path. GURL input(resolve_cases[i].base); GURL output = input.Resolve(resolve_cases[i].relative); @@ -383,7 +383,7 @@ {"blob:null/guid-goes-here", ""}, {"blob:http://origin/guid-goes-here", "" /* should be http://origin/ */}, }; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { GURL url(cases[i].input); GURL origin = url.DeprecatedGetOriginAsURL(); EXPECT_EQ(cases[i].expected, origin.spec()); @@ -406,7 +406,7 @@ {"file:///tmp/test.html", ""}, {"https://www.google.com", "https://www.google.com/"}, }; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { GURL url(cases[i].input); GURL origin = url.GetAsReferrer(); EXPECT_EQ(cases[i].expected, origin.spec()); @@ -425,7 +425,7 @@ {"filesystem:file:///temporary/bar.html?baz=22", "filesystem:file:///temporary/"}, }; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { GURL url(cases[i].input); GURL empty_path = url.GetWithEmptyPath(); EXPECT_EQ(cases[i].expected, empty_path.spec()); @@ -471,7 +471,7 @@ {"foobar", ""}, }; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { GURL url(cases[i].input); GURL without_filename = url.GetWithoutFilename(); EXPECT_EQ(cases[i].expected, without_filename.spec()) << i; @@ -636,7 +636,7 @@ "/foo/bar.html?query", "/temporary"}, }; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { GURL url(cases[i].input); EXPECT_EQ(cases[i].expected, url.PathForRequest()); EXPECT_EQ(cases[i].expected, url.PathForRequestPiece()); @@ -682,7 +682,7 @@ {"filesystem:file:///t/foo", PORT_UNSPECIFIED}, }; - for (size_t i = 0; i < gurl_base::size(port_tests); i++) { + for (size_t i = 0; i < std::size(port_tests); i++) { GURL url(port_tests[i].spec); EXPECT_EQ(port_tests[i].expected_int_port, url.EffectiveIntPort()); } @@ -703,7 +703,7 @@ {"some random input!", false}, }; - for (size_t i = 0; i < gurl_base::size(ip_tests); i++) { + for (size_t i = 0; i < std::size(ip_tests); i++) { GURL url(ip_tests[i].spec); EXPECT_EQ(ip_tests[i].expected_ip, url.HostIsIPAddress()); } @@ -728,7 +728,7 @@ {"http://]/", "]", "]"}, {"", "", ""}, }; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { GURL url(cases[i].input); EXPECT_EQ(cases[i].expected_host, url.host()); EXPECT_EQ(cases[i].expected_plainhost, url.HostNoBrackets());
diff --git a/url/origin.cc b/url/origin.cc index e943d4f..b17591d 100644 --- a/url/origin.cc +++ b/url/origin.cc
@@ -8,21 +8,23 @@ #include <algorithm> #include <ostream> -#include <vector> +#include <string> +#include <tuple> +#include <utility> #include "base/base64.h" +#include "polyfills/base/check.h" #include "polyfills/base/check_op.h" #include "base/containers/contains.h" #include "base/containers/span.h" +#include "base/debug/crash_logging.h" #include "base/pickle.h" #include "base/strings/strcat.h" -#include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" -#include "base/strings/string_util.h" +#include "base/unguessable_token.h" #include "polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h" #include "url/gurl.h" -#include "url/url_canon.h" -#include "url/url_canon_stdstring.h" +#include "url/scheme_host_port.h" #include "url/url_constants.h" #include "url/url_util.h" @@ -150,11 +152,8 @@ return tuple_.GetURL(); } -absl::optional<gurl_base::UnguessableToken> Origin::GetNonceForSerialization() - const { - // TODO(nasko): Consider not making a copy here, but return a reference to - // the nonce. - return nonce_ ? absl::make_optional(nonce_->token()) : absl::nullopt; +const gurl_base::UnguessableToken* Origin::GetNonceForSerialization() const { + return nonce_ ? &nonce_->token() : nullptr; } bool Origin::IsSameOriginWith(const Origin& other) const {
diff --git a/url/origin.h b/url/origin.h index c1ad177..1b0a407 100644 --- a/url/origin.h +++ b/url/origin.h
@@ -13,17 +13,15 @@ #include "polyfills/base/component_export.h" #include "polyfills/base/debug/alias.h" #include "base/debug/crash_logging.h" -#include "base/strings/string_piece.h" +#include "base/strings/string_piece_forward.h" #include "base/strings/string_util.h" #include "base/unguessable_token.h" #include "build/build_config.h" +#include "build/buildflag.h" #include "ipc/ipc_param_traits.h" #include "absl/types/optional.h" #include "polyfills/third_party/perfetto/include/perfetto/tracing/traced_value.h" #include "url/scheme_host_port.h" -#include "url/third_party/mozilla/url_parse.h" -#include "url/url_canon.h" -#include "url/url_constants.h" #if BUILDFLAG(IS_ANDROID) #include <jni.h> @@ -403,9 +401,10 @@ // given |nonce|. Origin(const Nonce& nonce, SchemeHostPort precursor); - // Get the nonce associated with this origin, if it is opaque. This should be - // used only when trying to send an Origin across an IPC pipe. - absl::optional<gurl_base::UnguessableToken> GetNonceForSerialization() const; + // Get the nonce associated with this origin, if it is opaque, or nullptr + // otherwise. This should be used only when trying to send an Origin across an + // IPC pipe. + const gurl_base::UnguessableToken* GetNonceForSerialization() const; // Serializes this Origin, including its nonce if it is opaque. If an opaque // origin's |tuple_| is invalid nullopt is returned. If the nonce is not
diff --git a/url/origin_unittest.cc b/url/origin_unittest.cc index 755d2e3..bd9ee7e 100644 --- a/url/origin_unittest.cc +++ b/url/origin_unittest.cc
@@ -69,7 +69,7 @@ return Origin::Nonce(nonce); } - absl::optional<gurl_base::UnguessableToken> GetNonce(const Origin& origin) { + const gurl_base::UnguessableToken* GetNonce(const Origin& origin) { return origin.GetNonceForSerialization(); } @@ -364,7 +364,7 @@ << "UnsafelyCreateOpaqueOriginWithoutNormalization, so long as it is " << "the canonical form of the invalid tuple."; EXPECT_TRUE(anonymous_opaque->opaque()); - EXPECT_EQ(GetNonce(anonymous_opaque.value()), token); + EXPECT_EQ(*GetNonce(anonymous_opaque.value()), token); EXPECT_EQ(anonymous_opaque->GetTupleOrPrecursorTupleIfOpaque(), url::SchemeHostPort()); }
diff --git a/url/scheme_host_port_unittest.cc b/url/scheme_host_port_unittest.cc index e55c9d5..f49bd59 100644 --- a/url/scheme_host_port_unittest.cc +++ b/url/scheme_host_port_unittest.cc
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "url/scheme_host_port.h" + #include <stddef.h> #include <stdint.h> -#include "base/cxx17_backports.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" -#include "url/scheme_host_port.h" #include "url/url_util.h" namespace { @@ -262,10 +262,10 @@ {"https", "b", 81}, }; - for (size_t i = 0; i < gurl_base::size(tuples); i++) { + for (size_t i = 0; i < std::size(tuples); i++) { url::SchemeHostPort current(tuples[i].scheme, tuples[i].host, tuples[i].port); - for (size_t j = i; j < gurl_base::size(tuples); j++) { + for (size_t j = i; j < std::size(tuples); j++) { url::SchemeHostPort to_compare(tuples[j].scheme, tuples[j].host, tuples[j].port); EXPECT_EQ(i < j, current < to_compare) << i << " < " << j;
diff --git a/url/third_party/mozilla/url_parse.cc b/url/third_party/mozilla/url_parse.cc index 8edb7f3..2500fc6 100644 --- a/url/third_party/mozilla/url_parse.cc +++ b/url/third_party/mozilla/url_parse.cc
@@ -692,6 +692,11 @@ } // namespace +COMPONENT_EXPORT(URL) +std::ostream& operator<<(std::ostream& os, const Component& component) { + return os << '{' << component.begin << ", " << component.len << "}"; +} + Parsed::Parsed() : potentially_dangling_markup(false), inner_parsed_(NULL) {} Parsed::Parsed(const Parsed& other)
diff --git a/url/third_party/mozilla/url_parse.h b/url/third_party/mozilla/url_parse.h index 1ec0ef8..c3535ba 100644 --- a/url/third_party/mozilla/url_parse.h +++ b/url/third_party/mozilla/url_parse.h
@@ -5,6 +5,8 @@ #ifndef URL_THIRD_PARTY_MOZILLA_URL_PARSE_H_ #define URL_THIRD_PARTY_MOZILLA_URL_PARSE_H_ +#include <iosfwd> + #include "polyfills/base/component_export.h" namespace url { @@ -47,6 +49,10 @@ int len; // Will be -1 if the component is unspecified. }; +// Permit printing Components by GURL_CHECK macros. +COMPONENT_EXPORT(URL) +std::ostream& operator<<(std::ostream& os, const Component& component); + // Helper that returns a component created with the given begin and ending // points. The ending point is non-inclusive. inline Component MakeRange(int begin, int end) {
diff --git a/url/url_canon.h b/url/url_canon.h index 32e7b15..e935d7f 100644 --- a/url/url_canon.h +++ b/url/url_canon.h
@@ -8,8 +8,6 @@ #include <stdlib.h> #include <string.h> -#include <string> - #include "polyfills/base/component_export.h" #include "polyfills/base/export_template.h" #include "url/third_party/mozilla/url_parse.h" @@ -299,7 +297,7 @@ // Piece-by-piece canonicalizers ---------------------------------------------- // // These individual canonicalizers append the canonicalized versions of the -// corresponding URL component to the given std::string. The spec and the +// corresponding URL component to the given CanonOutput. The spec and the // previously-identified range of that component are the input. The range of // the canonicalized component will be written to the output component. //
diff --git a/url/url_canon_icu_unittest.cc b/url/url_canon_icu_unittest.cc index 702b1d3..cb74f64 100644 --- a/url/url_canon_icu_unittest.cc +++ b/url/url_canon_icu_unittest.cc
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "url/url_canon_icu.h" + #include <stddef.h> -#include "base/cxx17_backports.h" #include "polyfills/base/logging.h" #include "base/memory/raw_ptr.h" #include "testing/gtest/include/gtest/gtest.h" #include <unicode/ucnv.h> #include "url/url_canon.h" -#include "url/url_canon_icu.h" #include "url/url_canon_stdstring.h" #include "url/url_test_utils.h" @@ -60,7 +60,7 @@ "hello\xa7\x41%26%231758%3B\xa6\x6eworld"}, }; - for (size_t i = 0; i < gurl_base::size(icu_cases); i++) { + for (size_t i = 0; i < std::size(icu_cases); i++) { UConvScoper conv(icu_cases[i].encoding); ASSERT_TRUE(conv.converter() != NULL); ICUCharsetConverter converter(conv.converter()); @@ -118,7 +118,7 @@ "?q=Chinese%26%2365319%3B"}, }; - for (size_t i = 0; i < gurl_base::size(query_cases); i++) { + for (size_t i = 0; i < std::size(query_cases); i++) { Component out_comp; UConvScoper conv(query_cases[i].encoding);
diff --git a/url/url_canon_unittest.cc b/url/url_canon_unittest.cc index 2dd5075..0170e00 100644 --- a/url/url_canon_unittest.cc +++ b/url/url_canon_unittest.cc
@@ -2,16 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "url/url_canon.h" + #include <errno.h> #include <stddef.h> -#include "base/cxx17_backports.h" #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" #include "base/test/gtest_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/third_party/mozilla/url_parse.h" -#include "url/url_canon.h" #include "url/url_canon_internal.h" #include "url/url_canon_stdstring.h" #include "url/url_test_utils.h" @@ -116,7 +116,7 @@ {0x10FFFF, "\xF4\x8F\xBF\xBF"}, }; std::string out_str; - for (size_t i = 0; i < gurl_base::size(utf_cases); i++) { + for (size_t i = 0; i < std::size(utf_cases); i++) { out_str.clear(); StdStringCanonOutput output(&out_str); AppendUTF8Value(utf_cases[i].input, &output); @@ -168,7 +168,7 @@ }; std::string out_str; - for (size_t i = 0; i < gurl_base::size(utf_cases); i++) { + for (size_t i = 0; i < std::size(utf_cases); i++) { if (utf_cases[i].input8) { out_str.clear(); StdStringCanonOutput output(&out_str); @@ -239,7 +239,7 @@ std::string out_str; - for (size_t i = 0; i < gurl_base::size(scheme_cases); i++) { + for (size_t i = 0; i < std::size(scheme_cases); i++) { int url_len = static_cast<int>(strlen(scheme_cases[i].input)); Component in_comp(0, url_len); Component out_comp; @@ -504,7 +504,7 @@ // CanonicalizeHost() non-verbose. std::string out_str; - for (size_t i = 0; i < gurl_base::size(host_cases); i++) { + for (size_t i = 0; i < std::size(host_cases); i++) { // Narrow version. if (host_cases[i].input8) { int host_len = static_cast<int>(strlen(host_cases[i].input8)); @@ -552,7 +552,7 @@ } // CanonicalizeHostVerbose() - for (size_t i = 0; i < gurl_base::size(host_cases); i++) { + for (size_t i = 0; i < std::size(host_cases); i++) { // Narrow version. if (host_cases[i].input8) { int host_len = static_cast<int>(strlen(host_cases[i].input8)); @@ -869,7 +869,7 @@ {"[::1 hello]", L"[::1 hello]", "", Component(), CanonHostInfo::BROKEN, -1, ""}, }; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { // 8-bit version. Component component(0, static_cast<int>(strlen(cases[i].input8))); @@ -995,7 +995,7 @@ {"ftp://me\\mydomain:pass@foo.com/", "", Component(0, -1), Component(0, -1), true}, }; - for (size_t i = 0; i < gurl_base::size(user_info_cases); i++) { + for (size_t i = 0; i < std::size(user_info_cases); i++) { int url_len = static_cast<int>(strlen(user_info_cases[i].input)); Parsed parsed; ParseStandardURL(user_info_cases[i].input, url_len, &parsed); @@ -1064,7 +1064,7 @@ {"80", PORT_UNSPECIFIED, ":80", Component(1, 2), true}, }; - for (size_t i = 0; i < gurl_base::size(port_cases); i++) { + for (size_t i = 0; i < std::size(port_cases); i++) { int url_len = static_cast<int>(strlen(port_cases[i].input)); Component in_comp(0, url_len); Component out_comp; @@ -1249,7 +1249,7 @@ } TEST(URLCanonTest, Path) { - DoPathTest(kCommonPathCases, gurl_base::size(kCommonPathCases), CanonicalizePath, + DoPathTest(kCommonPathCases, std::size(kCommonPathCases), CanonicalizePath, CanonicalizePath); // Manual test: embedded NULLs should be escaped and the URL should be marked @@ -1272,9 +1272,9 @@ {"", L"", "", Component(0, 0), true}, }; - DoPathTest(kCommonPathCases, gurl_base::size(kCommonPathCases), + DoPathTest(kCommonPathCases, std::size(kCommonPathCases), CanonicalizePartialPath, CanonicalizePartialPath); - DoPathTest(partial_path_cases, gurl_base::size(partial_path_cases), + DoPathTest(partial_path_cases, std::size(partial_path_cases), CanonicalizePartialPath, CanonicalizePartialPath); } @@ -1304,7 +1304,7 @@ {"q=\"asdf\"", L"q=\"asdf\"", "?q=%22asdf%22"}, }; - for (size_t i = 0; i < gurl_base::size(query_cases); i++) { + for (size_t i = 0; i < std::size(query_cases); i++) { Component out_comp; if (query_cases[i].input8) { @@ -1376,7 +1376,7 @@ {"#asdf", L"#asdf", "##asdf", Component(1, 5), true}, }; - for (size_t i = 0; i < gurl_base::size(ref_cases); i++) { + for (size_t i = 0; i < std::size(ref_cases); i++) { // 8-bit input if (ref_cases[i].input8) { int len = static_cast<int>(strlen(ref_cases[i].input8)); @@ -1491,7 +1491,7 @@ {R"(HTTP:S/5%\../>%41)", "http://s/%3EA", true}, }; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { int url_len = static_cast<int>(strlen(cases[i].input)); Parsed parsed; ParseStandardURL(cases[i].input, url_len, &parsed); @@ -1532,7 +1532,7 @@ "filesystem://a:b@google.com:22/foo?baz@cat"}, }; - for (size_t i = 0; i < gurl_base::size(replace_cases); i++) { + for (size_t i = 0; i < std::size(replace_cases); i++) { const ReplaceCase& cur = replace_cases[i]; int base_len = static_cast<int>(strlen(cur.base)); Parsed parsed; @@ -1632,7 +1632,7 @@ nullptr, nullptr, nullptr, "file:///C:/gaba?query#ref"}, }; - for (size_t i = 0; i < gurl_base::size(replace_cases); i++) { + for (size_t i = 0; i < std::size(replace_cases); i++) { const ReplaceCase& cur = replace_cases[i]; SCOPED_TRACE(cur.base); int base_len = static_cast<int>(strlen(cur.base)); @@ -1701,7 +1701,7 @@ "filesystem:http://bar.com:40/t/gaba?query#ref"}, }; - for (size_t i = 0; i < gurl_base::size(replace_cases); i++) { + for (size_t i = 0; i < std::size(replace_cases); i++) { const ReplaceCase& cur = replace_cases[i]; int base_len = static_cast<int>(strlen(cur.base)); Parsed parsed; @@ -1745,7 +1745,7 @@ nullptr, nullptr, "data:"}, }; - for (size_t i = 0; i < gurl_base::size(replace_cases); i++) { + for (size_t i = 0; i < std::size(replace_cases); i++) { const ReplaceCase& cur = replace_cases[i]; int base_len = static_cast<int>(strlen(cur.base)); Parsed parsed; @@ -1796,7 +1796,7 @@ {"mailto:addr1", NULL, NULL, NULL, NULL, NULL, NULL, NULL, "BLAH", "mailto:addr1"}, }; - for (size_t i = 0; i < gurl_base::size(replace_cases); i++) { + for (size_t i = 0; i < std::size(replace_cases); i++) { const ReplaceCase& cur = replace_cases[i]; int base_len = static_cast<int>(strlen(cur.base)); Parsed parsed; @@ -1909,7 +1909,7 @@ #endif // _WIN32 }; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { int url_len = static_cast<int>(strlen(cases[i].input)); Parsed parsed; ParseFileURL(cases[i].input, url_len, &parsed); @@ -1958,7 +1958,7 @@ {"FilEsysteM:htTp:E=/.", "filesystem:http://e%3D//", false}, }; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { int url_len = static_cast<int>(strlen(cases[i].input)); Parsed parsed; ParseFileSystemURL(cases[i].input, url_len, &parsed); @@ -1997,7 +1997,7 @@ {"javascript:\uFFFF", "javascript:%EF%BF%BD"}, }; - for (size_t i = 0; i < gurl_base::size(path_cases); i++) { + for (size_t i = 0; i < std::size(path_cases); i++) { int url_len = static_cast<int>(strlen(path_cases[i].input)); Parsed parsed; ParsePathURL(path_cases[i].input, url_len, true, &parsed); @@ -2035,7 +2035,7 @@ {"\uFFFF", L"\uFFFF", "%EF%BF%BD"}, }; - for (size_t i = 0; i < gurl_base::size(path_cases); i++) { + for (size_t i = 0; i < std::size(path_cases); i++) { // 8-bit string input std::string out_str; StdStringCanonOutput output(&out_str); @@ -2129,7 +2129,7 @@ Parsed parsed; Parsed out_parsed; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { int url_len = static_cast<int>(strlen(cases[i].input)); if (i == 0) { // The first test case purposely has a '\0' in it -- don't count it @@ -2399,7 +2399,7 @@ {"about:blank", false, false, "content://content.Provider/", true, false, true, ""}, }; - for (size_t i = 0; i < gurl_base::size(rel_cases); i++) { + for (size_t i = 0; i < std::size(rel_cases); i++) { const RelativeCase& cur_case = rel_cases[i]; Parsed parsed;
diff --git a/url/url_parse_unittest.cc b/url/url_parse_unittest.cc index 7cd3fe8..9a8bb57 100644 --- a/url/url_parse_unittest.cc +++ b/url/url_parse_unittest.cc
@@ -2,11 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "url/third_party/mozilla/url_parse.h" - #include <stddef.h> -#include "base/cxx17_backports.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/third_party/mozilla/url_parse.h" @@ -137,7 +134,7 @@ "http://user@", "http:", }; - for (size_t i = 0; i < gurl_base::size(length_cases); i++) { + for (size_t i = 0; i < std::size(length_cases); i++) { int true_length = static_cast<int>(strlen(length_cases[i])); Parsed parsed; @@ -196,7 +193,7 @@ {"file:///c:/foo", Parsed::HOST, true, 7}, {"file:///c:/foo", Parsed::PATH, true, 7}, }; - for (size_t i = 0; i < gurl_base::size(count_cases); i++) { + for (size_t i = 0; i < std::size(count_cases); i++) { int length = static_cast<int>(strlen(count_cases[i].url)); // Simple test to distinguish file and standard URLs. @@ -314,7 +311,7 @@ // Declared outside for loop to try to catch cases in init() where we forget // to reset something that is reset by the constructor. Parsed parsed; - for (size_t i = 0; i < gurl_base::size(cases); i++) { + for (size_t i = 0; i < std::size(cases); i++) { const char* url = cases[i].input; ParseStandardURL(url, static_cast<int>(strlen(url)), &parsed); int port = ParsePort(url, parsed.port); @@ -349,7 +346,7 @@ // Declared outside for loop to try to catch cases in init() where we forget // to reset something that is reset by the constructor. Parsed parsed; - for (size_t i = 0; i < gurl_base::size(path_cases); i++) { + for (size_t i = 0; i < std::size(path_cases); i++) { const char* url = path_cases[i].input; ParsePathURL(url, static_cast<int>(strlen(url)), false, &parsed); @@ -448,7 +445,7 @@ // Declared outside for loop to try to catch cases in init() where we forget // to reset something that is reset by the construtor. Parsed parsed; - for (size_t i = 0; i < gurl_base::size(file_cases); i++) { + for (size_t i = 0; i < std::size(file_cases); i++) { const char* url = file_cases[i].input; ParseFileURL(url, static_cast<int>(strlen(url)), &parsed); int port = ParsePort(url, parsed.port); @@ -509,7 +506,7 @@ {"http://www.google.com/foo;bar;html", "foo"}, }; - for (size_t i = 0; i < gurl_base::size(extract_cases); i++) { + for (size_t i = 0; i < std::size(extract_cases); i++) { const char* url = extract_cases[i].input; int len = static_cast<int>(strlen(url)); @@ -617,7 +614,7 @@ // Declared outside for loop to try to catch cases in init() where we forget // to reset something that is reset by the constructor. Parsed parsed; - for (size_t i = 0; i < gurl_base::size(mailto_cases); ++i) { + for (size_t i = 0; i < std::size(mailto_cases); ++i) { const char* url = mailto_cases[i].input; ParseMailtoURL(url, static_cast<int>(strlen(url)), &parsed); int port = ParsePort(url, parsed.port); @@ -649,7 +646,7 @@ // Declared outside for loop to try to catch cases in init() where we forget // to reset something that is reset by the constructor. Parsed parsed; - for (size_t i = 0; i < gurl_base::size(filesystem_cases); i++) { + for (size_t i = 0; i < std::size(filesystem_cases); i++) { const FileSystemURLParseCase* parsecase = &filesystem_cases[i]; const char* url = parsecase->input; ParseFileSystemURL(url, static_cast<int>(strlen(url)), &parsed);
diff --git a/url/url_util.cc b/url/url_util.cc index 3162fdf..26657f7 100644 --- a/url/url_util.cc +++ b/url/url_util.cc
@@ -438,6 +438,13 @@ // ref). Replacements<CHAR> replacements_no_scheme = replacements; replacements_no_scheme.SetScheme(NULL, Component()); + // If the input URL has potentially dangling markup, set the flag on the + // output too. Note that in some cases the replacement gets rid of the + // potentially dangling markup, but this ok since the check will fail + // closed. + if (parsed.potentially_dangling_markup) { + out_parsed->potentially_dangling_markup = true; + } return DoReplaceComponents(recanonicalized.data(), recanonicalized.length(), recanonicalized_parsed, replacements_no_scheme, charset_converter, output, out_parsed);
diff --git a/url/url_util_unittest.cc b/url/url_util_unittest.cc index 5255817..53aab7d 100644 --- a/url/url_util_unittest.cc +++ b/url/url_util_unittest.cc
@@ -6,7 +6,6 @@ #include <stddef.h> -#include "base/cxx17_backports.h" #include "base/strings/string_piece.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest-message.h" @@ -251,7 +250,7 @@ {"%e4%bd%a0%e5%a5%bd", "\xe4\xbd\xa0\xe5\xa5\xbd"}, }; - for (size_t i = 0; i < gurl_base::size(decode_cases); i++) { + for (size_t i = 0; i < std::size(decode_cases); i++) { const char* input = decode_cases[i].input; RawCanonOutputT<char16_t> output; DecodeURLEscapeSequences(input, strlen(input), @@ -333,7 +332,7 @@ "pqrstuvwxyz%7B%7C%7D~%7F"}, }; - for (size_t i = 0; i < gurl_base::size(encode_cases); i++) { + for (size_t i = 0; i < std::size(encode_cases); i++) { const char* input = encode_cases[i].input; RawCanonOutputT<char> buffer; EncodeURIComponent(input, strlen(input), &buffer); @@ -410,7 +409,7 @@ // adding the requested dot doesn't seem wrong either. {"aaa://a\\", "aaa:.", true, "aaa://a\\."}}; - for (size_t i = 0; i < gurl_base::size(resolve_non_standard_cases); i++) { + for (size_t i = 0; i < std::size(resolve_non_standard_cases); i++) { const ResolveRelativeCase& test_data = resolve_non_standard_cases[i]; Parsed base_parsed; ParsePathURL(test_data.base, strlen(test_data.base), false, &base_parsed); @@ -518,6 +517,26 @@ EXPECT_TRUE(replaced_parsed.potentially_dangling_markup); } +TEST_F(URLUtilTest, PotentiallyDanglingMarkupAfterSchemeOnlyReplacement) { + // Parse a URL with potentially dangling markup. + Parsed original_parsed; + RawCanonOutput<32> original; + const char* url = "http://example.com/\n/<path"; + Canonicalize(url, strlen(url), false, nullptr, &original, &original_parsed); + ASSERT_TRUE(original_parsed.potentially_dangling_markup); + + // Perform a replacement, and validate that the potentially_dangling_markup + // flag carried over to the new Parsed object. + Replacements<char> replacements; + const char* new_scheme = "https"; + replacements.SetScheme(new_scheme, Component(0, strlen(new_scheme))); + Parsed replaced_parsed; + RawCanonOutput<32> replaced; + ReplaceComponents(original.data(), original.length(), original_parsed, + replacements, nullptr, &replaced, &replaced_parsed); + EXPECT_TRUE(replaced_parsed.potentially_dangling_markup); +} + TEST_F(URLUtilTest, TestDomainIs) { const struct { const char* canonicalized_host;