Update googleurl to a2e9430da59b678c058131fee8aa04370b1f8eed

This uses the latest Chromium version from Wed Jul 6 15:47:16 2022 +0000

Change-Id: I100fa197b5967a1d1098e851f1059e7e30916b24
diff --git a/AUTHORS b/AUTHORS
index a68e49b..b81d16f 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -22,6 +22,7 @@
 Abhishek Agarwal <abhishek.a21@samsung.com>
 Abhishek Kanike <abhishek.ka@samsung.com>
 Abhishek Singh <abhi.rathore@samsung.com>
+Abin K Paul <abin.paul1@gmail.com>
 Abul Hasan Md Osama <ahm.osama@samsung.com>
 Adam Bonner <abonner-chromium@solscope.com>
 Adam Bujalski <abujalski@gmail.com>
@@ -382,6 +383,7 @@
 Ganesh Borle <ganesh.borle@samsung.com>
 Gao Chun <chun.gao@intel.com>
 Gao Chun <gaochun.dev@gmail.com>
+Gao Yu <wanggao@tencent.com>
 Gaurav Dhol <gaurav.dhol@einfochips.com>
 Gautham Banasandra <gautham.bangalore@gmail.com>
 George Adams <geoada@amazon.com>
@@ -471,6 +473,7 @@
 Isaac Murchie <murchieisaac@gmail.com>
 Isaac Reilly <reillyi@amazon.com>
 Ivan Naydonov <samogot@gmail.com>
+Ivan Pavlotskiy <ivan.pavlotskiy@lgepartner.com>
 Ivan Sham <ivansham@amazon.com>
 Jack Bates <jack@nottheoilrig.com>
 Jacky Hu <flameddd@gmail.com>
@@ -700,6 +703,7 @@
 Leo Wolf <jclw@ymail.com>
 Leon Han <leon.han@intel.com>
 Leung Wing Chung <lwchkg@gmail.com>
+Li Yanbo <liyanbo.monster@bytedance.com>
 Li Yin <li.yin@intel.com>
 Lidwine Genevet <lgenevet@cisco.com>
 Lin Sun <lin.sun@intel.com>
@@ -1139,10 +1143,12 @@
 Sunil Ratnu <sunil.ratnu@samsung.com>
 Sunitha Srivatsa <srivats@amazon.com>
 Sunwoo Nam <jegalzz88@gmail.com>
+Suresh Guttula <suresh.guttula@amd.corp-partner.google.com>
 Surya K M <suryagowda590@gmail.com>
 Sushma Venkatesh Reddy <sushma.venkatesh.reddy@intel.com>
 Suvanjan Mukherjee <suvanjanmukherjee@gmail.com>
 Suyambulingam R M <suyambu.rm@samsung.com>
+Suyash Nayan <suyashnyn1@gmail.com>
 Suyash Sengar <suyash.s@samsung.com>
 Swarali Raut <swarali.sr@samsung.com>
 Swati Jaiswal <swa.jaiswal@samsung.com>
@@ -1158,6 +1164,7 @@
 Taeseong Yu <yugeeklab@gmail.com>
 Taeyeon Kim <ssg9732@gmail.com>
 Tae Shin <taeshindev@gmail.com>
+Taher Ali <taher.dasten@gmail.com>
 Takaaki Suzuki <takaakisuzuki.14@gmail.com>
 Takahiro Aoyagi <hogehoge@gachapin.jp>
 Takashi Fujita <tgfjt.mail@gmail.com>
@@ -1328,6 +1335,7 @@
 Zhengkun Li <zhengkli@amazon.com>
 Zhenyu Liang <zhenyu.liang@intel.com>
 Zhenyu Shan <zhenyu.shan@intel.com>
+Zhibo Wang <zhibo1.wang@intel.com>
 Zhifei Fang <facetothefate@gmail.com>
 Zhiyuan Ye <zhiyuanye@tencent.com>
 Zhuoyu Qian <zhuoyu.qian@samsung.com>
diff --git a/base/BUILD b/base/BUILD
index f86c18b..69dffea 100644
--- a/base/BUILD
+++ b/base/BUILD
@@ -34,6 +34,8 @@
         "memory/raw_ptr.h",
         "memory/raw_ptr_exclusion.h",
         "no_destructor.h",
+        "numerics/safe_conversions.h",
+        "numerics/safe_conversions_impl.h",
         "ranges/algorithm.h",
         "ranges/functional.h",
         "ranges/ranges.h",
diff --git a/base/memory/raw_ptr.h b/base/memory/raw_ptr.h
index f1ef810..0b378f4 100644
--- a/base/memory/raw_ptr.h
+++ b/base/memory/raw_ptr.h
@@ -62,6 +62,14 @@
 // These classes/structures are part of the raw_ptr implementation.
 // DO NOT USE THESE CLASSES DIRECTLY YOURSELF.
 
+// This type trait verifies a type can be used as a pointer offset.
+//
+// We support pointer offsets in signed (ptrdiff_t) or unsigned (size_t) values.
+// Smaller types are also allowed.
+template <typename Z>
+static constexpr bool offset_type =
+    std::is_integral_v<Z> && sizeof(Z) <= sizeof(ptrdiff_t);
+
 struct RawPtrNoOpImpl {
   // Wraps a pointer.
   template <typename T>
@@ -105,8 +113,10 @@
   }
 
   // Advance the wrapped pointer by `delta_elems`.
-  template <typename T>
-  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, ptrdiff_t delta_elems) {
+  template <typename T,
+            typename Z,
+            typename = std::enable_if_t<offset_type<Z>, void>>
+  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
     return wrapped_ptr + delta_elems;
   }
 
@@ -119,6 +129,7 @@
 
   // This is for accounting only, used by unit tests.
   static ALWAYS_INLINE void IncrementSwapCountForTest() {}
+  static ALWAYS_INLINE void IncrementLessCountForTest() {}
   static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
 };
 
@@ -246,8 +257,10 @@
   }
 
   // Advance the wrapped pointer by `delta_elems`.
-  template <typename T>
-  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, ptrdiff_t delta_elems) {
+  template <typename T,
+            typename Z,
+            typename = std::enable_if_t<offset_type<Z>, void>>
+  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
     return wrapped_ptr + delta_elems;
   }
 
@@ -260,6 +273,7 @@
 
   // This is for accounting only, used by unit tests.
   static ALWAYS_INLINE void IncrementSwapCountForTest() {}
+  static ALWAYS_INLINE void IncrementLessCountForTest() {}
   static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
 
  private:
@@ -423,8 +437,10 @@
   }
 
   // Advance the wrapped pointer by `delta_elems`.
-  template <typename T>
-  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, ptrdiff_t delta_elems) {
+  template <typename T,
+            typename Z,
+            typename = std::enable_if_t<offset_type<Z>, void>>
+  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
 #if GURL_DCHECK_IS_ON() || BUILDFLAG(ENABLE_BACKUP_REF_PTR_SLOW_CHECKS)
     uintptr_t address = reinterpret_cast<uintptr_t>(wrapped_ptr);
     if (IsSupportedAndNotNull(address))
@@ -445,6 +461,7 @@
 
   // This is for accounting only, used by unit tests.
   static ALWAYS_INLINE void IncrementSwapCountForTest() {}
+  static ALWAYS_INLINE void IncrementLessCountForTest() {}
   static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
 
  private:
@@ -457,8 +474,17 @@
   static BASE_EXPORT NOINLINE void AcquireInternal(uintptr_t address);
   static BASE_EXPORT NOINLINE void ReleaseInternal(uintptr_t address);
   static BASE_EXPORT NOINLINE bool IsPointeeAlive(uintptr_t address);
-  static BASE_EXPORT NOINLINE bool IsValidDelta(uintptr_t address,
-                                                ptrdiff_t delta_in_bytes);
+  template <typename Z, typename = std::enable_if_t<offset_type<Z>, void>>
+  static ALWAYS_INLINE bool IsValidDelta(uintptr_t address, Z delta_in_bytes) {
+    if constexpr (std::is_signed_v<Z>)
+      return IsValidSignedDelta(address, ptrdiff_t{delta_in_bytes});
+    else
+      return IsValidUnsignedDelta(address, size_t{delta_in_bytes});
+  }
+  static BASE_EXPORT NOINLINE bool IsValidSignedDelta(uintptr_t address,
+                                                      ptrdiff_t delta_in_bytes);
+  static BASE_EXPORT NOINLINE bool IsValidUnsignedDelta(uintptr_t address,
+                                                        size_t delta_in_bytes);
 };
 
 #endif  // BUILDFLAG(USE_BACKUP_REF_PTR)
@@ -510,8 +536,10 @@
   }
 
   // Advance the wrapped pointer by `delta_elems`.
-  template <typename T>
-  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, ptrdiff_t delta_elems) {
+  template <typename T,
+            typename Z,
+            typename = std::enable_if_t<offset_type<Z>, void>>
+  static ALWAYS_INLINE T* Advance(T* wrapped_ptr, Z delta_elems) {
     return wrapped_ptr + delta_elems;
   }
 
@@ -524,6 +552,7 @@
 
   // This is for accounting only, used by unit tests.
   static ALWAYS_INLINE void IncrementSwapCountForTest() {}
+  static ALWAYS_INLINE void IncrementLessCountForTest() {}
   static ALWAYS_INLINE void IncrementPointerToMemberOperatorCountForTest() {}
 
  private:
@@ -657,7 +686,9 @@
 using RawPtrBanDanglingIfSupported = internal::RawPtrNoOpImpl;
 #endif
 
-template <typename T, typename Impl = RawPtrBanDanglingIfSupported>
+using DefaultRawPtrImpl = RawPtrBanDanglingIfSupported;
+
+template <typename T, typename Impl = DefaultRawPtrImpl>
 class TRIVIAL_ABI GSL_POINTER raw_ptr {
  public:
   static_assert(raw_ptr_traits::IsSupportedType<T>::value,
@@ -847,11 +878,15 @@
     --(*this);
     return result;
   }
-  ALWAYS_INLINE raw_ptr& operator+=(ptrdiff_t delta_elems) {
+  template <typename Z,
+            typename = std::enable_if_t<internal::offset_type<Z>, void>>
+  ALWAYS_INLINE raw_ptr& operator+=(Z delta_elems) {
     wrapped_ptr_ = Impl::Advance(wrapped_ptr_, delta_elems);
     return *this;
   }
-  ALWAYS_INLINE raw_ptr& operator-=(ptrdiff_t delta_elems) {
+  template <typename Z,
+            typename = std::enable_if_t<internal::offset_type<Z>, void>>
+  ALWAYS_INLINE raw_ptr& operator-=(Z delta_elems) {
     return *this += -delta_elems;
   }
 
@@ -1050,6 +1085,37 @@
   return lhs.GetForComparison() >= rhs.GetForComparison();
 }
 
+// Template helpers for working with T* or raw_ptr<T>.
+template <typename T>
+struct IsPointer : std::false_type {};
+
+template <typename T>
+struct IsPointer<T*> : std::true_type {};
+
+template <typename T, typename I>
+struct IsPointer<raw_ptr<T, I>> : std::true_type {};
+
+template <typename T>
+inline constexpr bool IsPointerV = IsPointer<T>::value;
+
+template <typename T>
+struct RemovePointer {
+  using type = T;
+};
+
+template <typename T>
+struct RemovePointer<T*> {
+  using type = T;
+};
+
+template <typename T, typename I>
+struct RemovePointer<raw_ptr<T, I>> {
+  using type = T;
+};
+
+template <typename T>
+using RemovePointerT = typename RemovePointer<T>::type;
+
 }  // namespace base
 
 using gurl_base::raw_ptr;
@@ -1065,21 +1131,70 @@
 // never be dereferenced after becoming dangling.
 using DisableDanglingPtrDetection = gurl_base::RawPtrMayDangle;
 
+// See `docs/dangling_ptr.md`
+// Annotates known dangling raw_ptr. Those haven't been triaged yet. All the
+// occurrences are meant to be removed. See https://cbug.com/1291138.
+using DanglingUntriaged = DisableDanglingPtrDetection;
+
+// The following template parameters are only meaningful when `raw_ptr`
+// is `MTECheckedPtr` (never the case unless a particular GN arg is set
+// true.) `raw_ptr` users need not worry about this and can refer solely
+// to `DisableDanglingPtrDetection` and `DanglingUntriaged` above.
+//
+// The `raw_ptr` definition allows users to specify an implementation.
+// When `MTECheckedPtr` is in play, we need to augment this
+// implementation setting with another layer that allows the `raw_ptr`
+// to degrade into the no-op version.
+#if defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+
+// Direct pass-through to no-op implementation.
+using DegradeToNoOpWhenMTE = gurl_base::internal::RawPtrNoOpImpl;
+
+// As above, but with the "untriaged dangling" annotation.
+using DanglingUntriagedDegradeToNoOpWhenMTE = gurl_base::internal::RawPtrNoOpImpl;
+
+// As above, but with the "explicitly disable protection" annotation.
+using DisableDanglingPtrDetectionDegradeToNoOpWhenMTE =
+    gurl_base::internal::RawPtrNoOpImpl;
+
+#else
+
+// Direct pass-through to default implementation specified by `raw_ptr`
+// template.
+using DegradeToNoOpWhenMTE = gurl_base::RawPtrBanDanglingIfSupported;
+
+// Direct pass-through to `DanglingUntriaged`.
+using DanglingUntriagedDegradeToNoOpWhenMTE = DanglingUntriaged;
+
+// Direct pass-through to `DisableDanglingPtrDetection`.
+using DisableDanglingPtrDetectionDegradeToNoOpWhenMTE =
+    DisableDanglingPtrDetection;
+
+#endif  // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
+
 namespace std {
 
 // Override so set/map lookups do not create extra raw_ptr. This also allows
 // dangling pointers to be used for lookup.
-template <typename T, typename I>
-struct less<raw_ptr<T, I>> {
+template <typename T, typename Impl>
+struct less<raw_ptr<T, Impl>> {
   using is_transparent = void;
 
-  bool operator()(const raw_ptr<T, I>& lhs, const raw_ptr<T, I>& rhs) const {
+  bool operator()(const raw_ptr<T, Impl>& lhs,
+                  const raw_ptr<T, Impl>& rhs) const {
+    Impl::IncrementLessCountForTest();
     return lhs < rhs;
   }
 
-  bool operator()(T* lhs, const raw_ptr<T, I>& rhs) const { return lhs < rhs; }
+  bool operator()(T* lhs, const raw_ptr<T, Impl>& rhs) const {
+    Impl::IncrementLessCountForTest();
+    return lhs < rhs;
+  }
 
-  bool operator()(const raw_ptr<T, I>& lhs, T* rhs) const { return lhs < rhs; }
+  bool operator()(const raw_ptr<T, Impl>& lhs, T* rhs) const {
+    Impl::IncrementLessCountForTest();
+    return lhs < rhs;
+  }
 };
 
 }  // namespace std
diff --git a/base/strings/escape.cc b/base/strings/escape.cc
index 011b79c..5cd770d 100644
--- a/base/strings/escape.cc
+++ b/base/strings/escape.cc
@@ -61,7 +61,7 @@
       escaped.push_back(IntToHex(c >> 4));
       escaped.push_back(IntToHex(c & 0xf));
     } else {
-      escaped.push_back(c);
+      escaped.push_back(static_cast<char>(c));
     }
   }
   return escaped;
@@ -198,8 +198,8 @@
   char most_sig_digit(escaped_text[index + 1]);
   char least_sig_digit(escaped_text[index + 2]);
   if (IsHexDigit(most_sig_digit) && IsHexDigit(least_sig_digit)) {
-    *value =
-        HexDigitToInt(most_sig_digit) * 16 + HexDigitToInt(least_sig_digit);
+    *value = static_cast<unsigned char>(HexDigitToInt(most_sig_digit) * 16 +
+                                        HexDigitToInt(least_sig_digit));
     return true;
   }
   return false;
@@ -236,7 +236,7 @@
     }
   }
 
-  int32_t char_index = 0;
+  size_t char_index = 0;
   // Check if the unicode "character" that was just unescaped is valid.
   if (!ReadUnicodeCharacter(reinterpret_cast<char*>(bytes), num_bytes,
                             &char_index, code_point_out)) {
@@ -253,10 +253,11 @@
 
 // This method takes a Unicode code point and returns true if it should be
 // unescaped, based on |rules|.
-bool ShouldUnescapeCodePoint(UnescapeRule::Type rules, uint32_t code_point) {
+bool ShouldUnescapeCodePoint(UnescapeRule::Type rules,
+                             base_icu::UChar32 code_point) {
   // If this is an ASCII character, use the lookup table.
-  if (code_point < 0x80) {
-    return kUrlUnescape[code_point] ||
+  if (code_point >= 0 && code_point < 0x80) {
+    return kUrlUnescape[static_cast<size_t>(code_point)] ||
            // Allow some additional unescaping when flags are set.
            (code_point == ' ' && (rules & UnescapeRule::SPACES)) ||
            // Allow any of the prohibited but non-control characters when doing
@@ -418,7 +419,7 @@
       // sequences.
       unsigned char non_utf8_byte;
       if (UnescapeUnsignedByteAtIndex(escaped_text, i, &non_utf8_byte)) {
-        result.push_back(non_utf8_byte);
+        result.push_back(static_cast<char>(non_utf8_byte));
         if (adjustments)
           adjustments->push_back(OffsetAdjuster::Adjustment(i, 3, 1));
         i += 3;
@@ -569,7 +570,7 @@
     // UnescapeUnsignedByteAtIndex does bounds checking, so this is always safe
     // to call.
     if (UnescapeUnsignedByteAtIndex(escaped_text, i, &byte)) {
-      unescaped_text[output_index++] = byte;
+      unescaped_text[output_index++] = static_cast<char>(byte);
       i += 3;
       continue;
     }
@@ -595,7 +596,7 @@
   unescaped_text->clear();
 
   std::set<unsigned char> illegal_encoded_bytes;
-  for (char c = '\x00'; c < '\x20'; ++c) {
+  for (unsigned char c = '\x00'; c < '\x20'; ++c) {
     illegal_encoded_bytes.insert(c);
   }
   if (fail_on_path_separators) {
@@ -632,7 +633,7 @@
 std::u16string UnescapeForHTML(StringPiece16 input) {
   static const struct {
     const char* ampersand_code;
-    const char replacement;
+    const char16_t replacement;
   } kEscapeToChars[] = {
       {"&lt;", '<'},   {"&gt;", '>'},   {"&amp;", '&'},
       {"&quot;", '"'}, {"&#39;", '\''},
@@ -648,14 +649,15 @@
        ++iter) {
     if (*iter == '&') {
       // Potential ampersand encode char.
-      size_t index = iter - text.begin();
+      size_t index = static_cast<size_t>(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);
+          text.replace(
+              iter, iter + static_cast<ptrdiff_t>(ampersand_chars[i].length()),
+              1, kEscapeToChars[i].replacement);
           break;
         }
       }
diff --git a/base/strings/escape.h b/base/strings/escape.h
index 57f2f9a..02203be 100644
--- a/base/strings/escape.h
+++ b/base/strings/escape.h
@@ -74,41 +74,39 @@
   // functions.
   typedef uint32_t Type;
 
-  enum {
-    // Don't unescape anything at all.
-    NONE = 0,
+  // Don't unescape anything at all.
+  static constexpr Type NONE = 0;
 
-    // Don't unescape anything special, but all normal unescaping will happen.
-    // This is a placeholder and can't be combined with other flags (since it's
-    // just the absence of them). All other unescape rules imply "normal" in
-    // addition to their special meaning. Things like escaped letters, digits,
-    // and most symbols will get unescaped with this mode.
-    NORMAL = 1 << 0,
+  // Don't unescape anything special, but all normal unescaping will happen.
+  // This is a placeholder and can't be combined with other flags (since it's
+  // just the absence of them). All other unescape rules imply "normal" in
+  // addition to their special meaning. Things like escaped letters, digits,
+  // and most symbols will get unescaped with this mode.
+  static constexpr Type NORMAL = 1 << 0;
 
-    // Convert %20 to spaces. In some places where we're showing URLs, we may
-    // want this. In places where the URL may be copied and pasted out, then
-    // you wouldn't want this since it might not be interpreted in one piece
-    // by other applications.  Other UTF-8 spaces will not be unescaped.
-    SPACES = 1 << 1,
+  // Convert %20 to spaces. In some places where we're showing URLs, we may
+  // want this. In places where the URL may be copied and pasted out, then
+  // you wouldn't want this since it might not be interpreted in one piece
+  // by other applications.  Other UTF-8 spaces will not be unescaped.
+  static constexpr Type SPACES = 1 << 1;
 
-    // Unescapes '/' and '\\'. If these characters were unescaped, the resulting
-    // URL won't be the same as the source one. Moreover, they are dangerous to
-    // unescape in strings that will be used as file paths or names. This value
-    // should only be used when slashes don't have special meaning, like data
-    // URLs.
-    PATH_SEPARATORS = 1 << 2,
+  // Unescapes '/' and '\\'. If these characters were unescaped, the resulting
+  // URL won't be the same as the source one. Moreover, they are dangerous to
+  // unescape in strings that will be used as file paths or names. This value
+  // should only be used when slashes don't have special meaning, like data
+  // URLs.
+  static constexpr Type PATH_SEPARATORS = 1 << 2;
 
-    // Unescapes various characters that will change the meaning of URLs,
-    // including '%', '+', '&', '#'. Does not unescape path separators.
-    // If these characters were unescaped, the resulting URL won't be the same
-    // as the source one. This flag is used when generating final output like
-    // filenames for URLs where we won't be interpreting as a URL and want to do
-    // as much unescaping as possible.
-    URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS = 1 << 3,
+  // Unescapes various characters that will change the meaning of URLs,
+  // including '%', '+', '&', '#'. Does not unescape path separators.
+  // If these characters were unescaped, the resulting URL won't be the same
+  // as the source one. This flag is used when generating final output like
+  // filenames for URLs where we won't be interpreting as a URL and want to do
+  // as much unescaping as possible.
+  static constexpr Type URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS = 1 << 3;
 
-    // URL queries use "+" for space. This flag controls that replacement.
-    REPLACE_PLUS_WITH_SPACE = 1 << 4,
-  };
+  // URL queries use "+" for space. This flag controls that replacement.
+  static constexpr Type REPLACE_PLUS_WITH_SPACE = 1 << 4;
 };
 
 // Unescapes |escaped_text| and returns the result.
diff --git a/base/strings/pattern.cc b/base/strings/pattern.cc
index d7c9a47..607d6d5 100644
--- a/base/strings/pattern.cc
+++ b/base/strings/pattern.cc
@@ -124,7 +124,7 @@
   base_icu::UChar32 operator()(const char** p, const char* end) {
     base_icu::UChar32 c;
     int offset = 0;
-    CBU8_NEXT(*p, offset, end - *p, c);
+    CBU8_NEXT(reinterpret_cast<const uint8_t*>(*p), offset, end - *p, c);
     *p += offset;
     return c;
   }
diff --git a/base/strings/safe_sprintf.cc b/base/strings/safe_sprintf.cc
index 6c9aa19..26a7715 100644
--- a/base/strings/safe_sprintf.cc
+++ b/base/strings/safe_sprintf.cc
@@ -223,8 +223,13 @@
   // if |pad| is ' '.
   //
   // Returns "false", if the |buffer_| overflowed at any time.
-  bool IToASCII(bool sign, bool upcase, int64_t i, int base,
-                char pad, size_t padding, const char* prefix);
+  bool IToASCII(bool sign,
+                bool upcase,
+                int64_t i,
+                size_t base,
+                char pad,
+                size_t padding,
+                const char* prefix);
 
  private:
   // Increments |count_| by |inc| unless this would cause |count_| to
@@ -275,9 +280,13 @@
   size_t count_;
 };
 
-
-bool Buffer::IToASCII(bool sign, bool upcase, int64_t i, int base,
-                      char pad, size_t padding, const char* prefix) {
+bool Buffer::IToASCII(bool sign,
+                      bool upcase,
+                      int64_t i,
+                      size_t base,
+                      char pad,
+                      size_t padding,
+                      const char* prefix) {
   // Sanity check for parameters. None of these should ever fail, but see
   // above for the rationale why we can't call GURL_CHECK().
   DEBUG_CHECK(base >= 2);
@@ -295,7 +304,7 @@
   //   if (sign && i < 0)
   //     prefix = "-";
   //   num = abs(i);
-  int minint = 0;
+  size_t minint = 0;
   uint64_t num;
   if (sign && i < 0) {
     prefix = "-";
@@ -335,7 +344,7 @@
     }
   } else
     prefix = nullptr;
-  const size_t prefix_length = reverse_prefix - prefix;
+  const size_t prefix_length = static_cast<size_t>(reverse_prefix - prefix);
 
   // Loop until we have converted the entire number. Output at least one
   // character (i.e. '0').
@@ -384,7 +393,8 @@
       }
     } else {
       started = true;
-      Out((upcase ? kUpCaseHexDigits : kDownCaseHexDigits)[num%base + minint]);
+      Out((upcase ? kUpCaseHexDigits
+                  : kDownCaseHexDigits)[num % base + minint]);
     }
 
     minint = 0;
@@ -457,13 +467,14 @@
         // character from a space ' ' to a zero '0'.
         pad = ch == '0' ? '0' : ' ';
         for (;;) {
+          const size_t digit = static_cast<size_t>(ch - '0');
           // The maximum allowed padding fills all the available address
           // space and leaves just enough space to insert the trailing NUL.
           const size_t max_padding = kSSizeMax - 1;
-          if (padding > max_padding/10 ||
-              10*padding > max_padding - (ch - '0')) {
-            DEBUG_CHECK(padding <= max_padding/10 &&
-                        10*padding <= max_padding - (ch - '0'));
+          if (padding > max_padding / 10 ||
+              10 * padding > max_padding - digit) {
+            DEBUG_CHECK(padding <= max_padding / 10 &&
+                        10 * padding <= max_padding - digit);
             // Integer overflow detected. Skip the rest of the width until
             // we find the format character, then do the normal error handling.
           padding_overflow:
@@ -475,7 +486,7 @@
             }
             goto fail_to_expand;
           }
-          padding = 10*padding + ch - '0';
+          padding = 10 * padding + digit;
           if (padding > max_padding) {
             // This doesn't happen for "sane" values of kSSizeMax. But once
             // kSSizeMax gets smaller than about 10, our earlier range checks
@@ -552,9 +563,9 @@
         } else {
           // Pointer values require an actual pointer or a string.
           if (arg.type == Arg::POINTER) {
-            i = reinterpret_cast<uintptr_t>(arg.ptr);
+            i = static_cast<int64_t>(reinterpret_cast<uintptr_t>(arg.ptr));
           } else if (arg.type == Arg::STRING) {
-            i = reinterpret_cast<uintptr_t>(arg.str);
+            i = static_cast<int64_t>(reinterpret_cast<uintptr_t>(arg.str));
           } else if (arg.type == Arg::INT &&
                      arg.integer.width == sizeof(NULL) &&
                      arg.integer.i == 0) {  // Allow C++'s version of NULL
diff --git a/base/strings/safe_sprintf.h b/base/strings/safe_sprintf.h
index 8e6c922..a5b242b 100644
--- a/base/strings/safe_sprintf.h
+++ b/base/strings/safe_sprintf.h
@@ -167,7 +167,7 @@
     integer.width = sizeof(long);
   }
   Arg(unsigned long j) : type(UINT) {
-    integer.i = j;
+    integer.i = static_cast<int64_t>(j);
     integer.width = sizeof(long);
   }
   Arg(signed long long j) : type(INT) {
diff --git a/base/strings/safe_sprintf_unittest.cc b/base/strings/safe_sprintf_unittest.cc
index 71814b3..ad1cca2 100644
--- a/base/strings/safe_sprintf_unittest.cc
+++ b/base/strings/safe_sprintf_unittest.cc
@@ -337,22 +337,23 @@
 
   // Pointer
   char addr[20];
-  sprintf(addr, "0x%llX", (unsigned long long)(uintptr_t)buf);
+  snprintf(addr, sizeof(addr), "0x%llX", (unsigned long long)(uintptr_t)buf);
   SafeSPrintf(buf, "%p", buf);
   EXPECT_EQ(std::string(addr), std::string(buf));
   SafeSPrintf(buf, "%p", (const char *)buf);
   EXPECT_EQ(std::string(addr), std::string(buf));
-  sprintf(addr, "0x%llX", (unsigned long long)(uintptr_t)sprintf);
-  SafeSPrintf(buf, "%p", sprintf);
+  snprintf(addr, sizeof(addr), "0x%llX",
+           (unsigned long long)(uintptr_t)snprintf);
+  SafeSPrintf(buf, "%p", snprintf);
   EXPECT_EQ(std::string(addr), std::string(buf));
 
   // Padding for pointers is a little more complicated because of the "0x"
   // prefix. Padding with '0' zeros is relatively straight-forward, but
   // padding with ' ' spaces requires more effort.
-  sprintf(addr, "0x%017llX", (unsigned long long)(uintptr_t)buf);
+  snprintf(addr, sizeof(addr), "0x%017llX", (unsigned long long)(uintptr_t)buf);
   SafeSPrintf(buf, "%019p", buf);
   EXPECT_EQ(std::string(addr), std::string(buf));
-  sprintf(addr, "0x%llX", (unsigned long long)(uintptr_t)buf);
+  snprintf(addr, sizeof(addr), "0x%llX", (unsigned long long)(uintptr_t)buf);
   memset(addr, ' ',
          (char*)memmove(addr + sizeof(addr) - strlen(addr) - 1,
                         addr, strlen(addr)+1) - addr);
@@ -427,8 +428,8 @@
     EXPECT_EQ('X', tmp[i]);
 
   // The text that was generated by SafeSPrintf() should always match the
-  // equivalent text generated by sprintf(). Please note that the format
-  // string for sprintf() is not complicated, as it does not have the
+  // equivalent text generated by snprintf(). Please note that the format
+  // string for snprintf() is not complicated, as it does not have the
   // benefit of getting type information from the C++ compiler.
   //
   // N.B.: It would be so much cleaner to use snprintf(). But unfortunately,
@@ -436,10 +437,10 @@
   //       are all really awkward.
   char ref[256];
   GURL_CHECK_LE(sz, sizeof(ref));
-  sprintf(ref, "A long string: %%d 00DEADBEEF %lld 0x%llX <NULL>",
-          static_cast<long long>(std::numeric_limits<intptr_t>::min()),
-          static_cast<unsigned long long>(
-            reinterpret_cast<uintptr_t>(PrintLongString)));
+  snprintf(ref, sizeof(ref), "A long string: %%d 00DEADBEEF %lld 0x%llX <NULL>",
+           static_cast<long long>(std::numeric_limits<intptr_t>::min()),
+           static_cast<unsigned long long>(
+               reinterpret_cast<uintptr_t>(PrintLongString)));
   ref[sz-1] = '\000';
 
 #if defined(NDEBUG)
@@ -448,7 +449,7 @@
   const size_t kSSizeMax = internal::GetSafeSPrintfSSizeMaxForTest();
 #endif
 
-  // Compare the output from SafeSPrintf() to the one from sprintf().
+  // Compare the output from SafeSPrintf() to the one from snprintf().
   EXPECT_EQ(std::string(ref).substr(0, kSSizeMax-1), std::string(tmp.get()));
 
   // We allocated a slightly larger buffer, so that we could perform some
diff --git a/base/strings/string_number_conversions_internal.h b/base/strings/string_number_conversions_internal.h
index 2abd324..7c1804c 100644
--- a/base/strings/string_number_conversions_internal.h
+++ b/base/strings/string_number_conversions_internal.h
@@ -61,13 +61,13 @@
 absl::optional<uint8_t> CharToDigit(CHAR c) {
   static_assert(1 <= BASE && BASE <= 36, "BASE needs to be in [1, 36]");
   if (c >= '0' && c < '0' + std::min(BASE, 10))
-    return c - '0';
+    return static_cast<uint8_t>(c - '0');
 
   if (c >= 'a' && c < 'a' + BASE - 10)
-    return c - 'a' + 10;
+    return static_cast<uint8_t>(c - 'a' + 10);
 
   if (c >= 'A' && c < 'A' + BASE - 10)
-    return c - 'A' + 10;
+    return static_cast<uint8_t>(c - 'A' + 10);
 
   return absl::nullopt;
 }
diff --git a/base/strings/string_piece.cc b/base/strings/string_piece.cc
index f9b9422..e76e6ad 100644
--- a/base/strings/string_piece.cc
+++ b/base/strings/string_piece.cc
@@ -129,7 +129,7 @@
                                          s.begin(), s.end());
   if (found == self.end())
     return BasicStringPiece<CharT>::npos;
-  return found - self.begin();
+  return static_cast<size_t>(found - self.begin());
 }
 
 size_t find_first_of(StringPiece16 self, StringPiece16 s, size_t pos) {
diff --git a/base/strings/string_util.cc b/base/strings/string_util.cc
index 8729bf4..8623096 100644
--- a/base/strings/string_util.cc
+++ b/base/strings/string_util.cc
@@ -174,7 +174,8 @@
   while (char_index >= 0) {
     int32_t prev = char_index;
     base_icu::UChar32 code_point = 0;
-    CBU8_NEXT(data, char_index, truncation_length, code_point);
+    CBU8_NEXT(reinterpret_cast<const uint8_t*>(data), char_index,
+              truncation_length, code_point);
     if (!IsValidCharacter(code_point)) {
       char_index = prev - 1;
     } else {
@@ -183,7 +184,7 @@
   }
 
   if (char_index >= 0 )
-    *output = input.substr(0, char_index);
+    *output = input.substr(0, static_cast<size_t>(char_index));
   else
     output->clear();
 }
@@ -254,14 +255,6 @@
   return internal::DoIsStringUTF8<IsValidCodepoint>(str);
 }
 
-bool LowerCaseEqualsASCII(StringPiece str, StringPiece lowercase_ascii) {
-  return internal::DoLowerCaseEqualsASCII(str, lowercase_ascii);
-}
-
-bool LowerCaseEqualsASCII(StringPiece16 str, StringPiece lowercase_ascii) {
-  return internal::DoLowerCaseEqualsASCII(str, lowercase_ascii);
-}
-
 bool EqualsASCII(StringPiece16 str, StringPiece ascii) {
   return std::equal(ascii.begin(), ascii.end(), str.begin(), str.end());
 }
diff --git a/base/strings/string_util.h b/base/strings/string_util.h
index 435b5c6..c3224f1 100644
--- a/base/strings/string_util.h
+++ b/base/strings/string_util.h
@@ -337,13 +337,6 @@
 BASE_EXPORT bool IsStringASCII(WStringPiece str);
 #endif
 
-// Compare the lower-case form of the given string against the given
-// previously-lower-cased ASCII string (typically a constant).
-BASE_EXPORT bool LowerCaseEqualsASCII(StringPiece str,
-                                      StringPiece lowercase_ascii);
-BASE_EXPORT bool LowerCaseEqualsASCII(StringPiece16 str,
-                                      StringPiece lowercase_ascii);
-
 // Performs a case-sensitive string compare of the given 16-bit string against
 // the given 8-bit ASCII string (typically a constant). The behavior is
 // undefined if the |ascii| string is not ASCII.
diff --git a/base/strings/string_util_internal.h b/base/strings/string_util_internal.h
index 173cfaa..8608eba 100644
--- a/base/strings/string_util_internal.h
+++ b/base/strings/string_util_internal.h
@@ -242,28 +242,6 @@
   return true;
 }
 
-// Implementation note: Normally this function will be called with a hardcoded
-// constant for the lowercase_ascii parameter. Constructing a StringPiece from
-// a C constant requires running strlen, so the result will be two passes
-// through the buffers, one to file the length of lowercase_ascii, and one to
-// compare each letter.
-//
-// This function could have taken a const char* to avoid this and only do one
-// pass through the string. But the strlen is faster than the case-insensitive
-// compares and lets us early-exit in the case that the strings are different
-// lengths (will often be the case for non-matches). So whether one approach or
-// the other will be faster depends on the case.
-//
-// The hardcoded strings are typically very short so it doesn't matter, and the
-// string piece gives additional flexibility for the caller (doesn't have to be
-// null terminated) so we choose the StringPiece route.
-template <typename T, typename CharT = typename T::value_type>
-inline bool DoLowerCaseEqualsASCII(T str, StringPiece lowercase_ascii) {
-  return std::equal(
-      str.begin(), str.end(), lowercase_ascii.begin(), lowercase_ascii.end(),
-      [](auto lhs, auto rhs) { return ToLowerASCII(lhs) == rhs; });
-}
-
 template <typename T, typename CharT = typename T::value_type>
 bool StartsWithT(T str, T search_for, CompareCase case_sensitivity) {
   if (search_for.size() > str.size())
diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc
index f41f6d8..4d2ac71 100644
--- a/base/strings/string_util_unittest.cc
+++ b/base/strings/string_util_unittest.cc
@@ -660,22 +660,6 @@
   EXPECT_EQ(u"CC2", ToUpperASCII(u"Cc2"));
 }
 
-TEST(StringUtilTest, LowerCaseEqualsASCII) {
-  static const struct {
-    const char*    src_a;
-    const char*    dst;
-  } lowercase_cases[] = {
-    { "FoO", "foo" },
-    { "foo", "foo" },
-    { "FOO", "foo" },
-  };
-
-  for (const auto& i : lowercase_cases) {
-    EXPECT_TRUE(LowerCaseEqualsASCII(ASCIIToUTF16(i.src_a), i.dst));
-    EXPECT_TRUE(LowerCaseEqualsASCII(i.src_a, i.dst));
-  }
-}
-
 TEST(StringUtilTest, FormatBytesUnlocalized) {
   static const struct {
     int64_t bytes;
diff --git a/base/strings/string_util_win.cc b/base/strings/string_util_win.cc
index 7a9b891..7ab9061 100644
--- a/base/strings/string_util_win.cc
+++ b/base/strings/string_util_win.cc
@@ -71,10 +71,6 @@
   return input.find_first_not_of(characters) == StringPiece::npos;
 }
 
-bool LowerCaseEqualsASCII(WStringPiece str, StringPiece lowercase_ascii) {
-  return internal::DoLowerCaseEqualsASCII(str, lowercase_ascii);
-}
-
 bool EqualsASCII(WStringPiece str, StringPiece ascii) {
   return std::equal(ascii.begin(), ascii.end(), str.begin(), str.end());
 }
diff --git a/base/strings/string_util_win.h b/base/strings/string_util_win.h
index fbf815b..6b5fba3 100644
--- a/base/strings/string_util_win.h
+++ b/base/strings/string_util_win.h
@@ -157,9 +157,6 @@
 
 BASE_EXPORT bool ContainsOnlyChars(WStringPiece input, WStringPiece characters);
 
-BASE_EXPORT bool LowerCaseEqualsASCII(WStringPiece str,
-                                      StringPiece lowercase_ascii);
-
 BASE_EXPORT bool EqualsASCII(StringPiece16 str, StringPiece ascii);
 
 BASE_EXPORT bool StartsWith(
diff --git a/base/strings/stringprintf.cc b/base/strings/stringprintf.cc
index e0c5e20..8de48f3 100644
--- a/base/strings/stringprintf.cc
+++ b/base/strings/stringprintf.cc
@@ -65,14 +65,14 @@
   int result = vsnprintfT(stack_buf, std::size(stack_buf), format, ap_copy);
   va_end(ap_copy);
 
-  if (result >= 0 && result < static_cast<int>(std::size(stack_buf))) {
+  if (result >= 0 && static_cast<size_t>(result) < std::size(stack_buf)) {
     // It fit.
-    dst->append(stack_buf, result);
+    dst->append(stack_buf, static_cast<size_t>(result));
     return;
   }
 
   // Repeatedly increase buffer size until it fits.
-  int mem_length = std::size(stack_buf);
+  size_t mem_length = std::size(stack_buf);
   while (true) {
     if (result < 0) {
 #if BUILDFLAG(IS_WIN)
@@ -88,7 +88,7 @@
 #endif
     } else {
       // We need exactly "result + 1" characters.
-      mem_length = result + 1;
+      mem_length = static_cast<size_t>(result) + 1;
     }
 
     if (mem_length > 32 * 1024 * 1024) {
@@ -107,9 +107,9 @@
     result = vsnprintfT(&mem_buf[0], mem_length, format, ap_copy);
     va_end(ap_copy);
 
-    if ((result >= 0) && (result < mem_length)) {
+    if ((result >= 0) && (static_cast<size_t>(result) < mem_length)) {
       // It fit.
-      dst->append(&mem_buf[0], result);
+      dst->append(&mem_buf[0], static_cast<size_t>(result));
       return;
     }
   }
diff --git a/base/strings/sys_string_conversions_win.cc b/base/strings/sys_string_conversions_win.cc
index 3f08956..c0b4829 100644
--- a/base/strings/sys_string_conversions_win.cc
+++ b/base/strings/sys_string_conversions_win.cc
@@ -42,7 +42,7 @@
     return std::wstring();
 
   std::wstring wide;
-  wide.resize(charcount);
+  wide.resize(static_cast<size_t>(charcount));
   MultiByteToWideChar(code_page, 0, mb.data(), mb_length, &wide[0], charcount);
 
   return wide;
@@ -61,7 +61,7 @@
     return std::string();
 
   std::string mb;
-  mb.resize(charcount);
+  mb.resize(static_cast<size_t>(charcount));
   WideCharToMultiByte(code_page, 0, wide.data(), wide_length,
                       &mb[0], charcount, NULL, NULL);
 
diff --git a/base/strings/utf_offset_string_conversions.cc b/base/strings/utf_offset_string_conversions.cc
index e6bb6d6..b67b6a7 100644
--- a/base/strings/utf_offset_string_conversions.cc
+++ b/base/strings/utf_offset_string_conversions.cc
@@ -39,7 +39,8 @@
   GURL_DCHECK(offset);
   if (*offset == std::u16string::npos)
     return;
-  int adjustment = 0;
+  size_t original_lengths = 0;
+  size_t output_lengths = 0;
   for (const auto& i : adjustments) {
     if (*offset <= i.original_offset)
       break;
@@ -47,9 +48,10 @@
       *offset = std::u16string::npos;
       return;
     }
-    adjustment += static_cast<int>(i.original_length - i.output_length);
+    original_lengths += i.original_length;
+    output_lengths += i.output_length;
   }
-  *offset -= adjustment;
+  *offset += output_lengths - original_lengths;
 
   if (*offset > limit)
     *offset = std::u16string::npos;
@@ -70,17 +72,20 @@
                                     size_t* offset) {
   if (*offset == std::u16string::npos)
     return;
-  int adjustment = 0;
+  size_t original_lengths = 0;
+  size_t output_lengths = 0;
   for (const auto& i : adjustments) {
-    if (*offset + adjustment <= i.original_offset)
+    if (*offset + original_lengths - output_lengths <= i.original_offset)
       break;
-    adjustment += static_cast<int>(i.original_length - i.output_length);
-    if ((*offset + adjustment) < (i.original_offset + i.original_length)) {
+    original_lengths += i.original_length;
+    output_lengths += i.output_length;
+    if ((*offset + original_lengths - output_lengths) <
+        (i.original_offset + i.original_length)) {
       *offset = std::u16string::npos;
       return;
     }
   }
-  *offset += adjustment;
+  *offset += original_lengths - output_lengths;
 }
 
 // static
@@ -149,15 +154,15 @@
       //   <=
       //   adjusted_iter->original_offset + shift +
       //       adjusted_iter->original_length
-
       // Modify the current |adjusted_iter| to include whatever collapsing
       // happened in |first_iter|, then advance to the next |first_adjustments|
       // because we dealt with the current one.
-      const int collapse = static_cast<int>(first_iter->original_length) -
-          static_cast<int>(first_iter->output_length);
+
       // This function does not know how to deal with a string that expands and
       // then gets modified, only strings that collapse and then get modified.
-      GURL_DCHECK_GT(collapse, 0);
+      GURL_DCHECK_GT(first_iter->original_length, first_iter->output_length);
+      const size_t collapse =
+          first_iter->original_length - first_iter->output_length;
       adjusted_iter->original_length += collapse;
       currently_collapsing += collapse;
       ++first_iter;
@@ -188,14 +193,12 @@
                     OffsetAdjuster::Adjustments* adjustments) {
   if (adjustments)
     adjustments->clear();
-  // ICU requires 32-bit numbers.
   bool success = true;
-  int32_t src_len32 = static_cast<int32_t>(src_len);
-  for (int32_t i = 0; i < src_len32; i++) {
+  for (size_t i = 0; i < src_len; i++) {
     base_icu::UChar32 code_point;
     size_t original_i = i;
     size_t chars_written = 0;
-    if (ReadUnicodeCharacter(src, src_len32, &i, &code_point)) {
+    if (ReadUnicodeCharacter(src, src_len, &i, &code_point)) {
       chars_written = WriteUnicodeCharacter(code_point, output);
     } else {
       chars_written = WriteUnicodeCharacter(0xFFFD, output);
diff --git a/base/strings/utf_string_conversion_utils.cc b/base/strings/utf_string_conversion_utils.cc
index 76dd725..3ddcc7b 100644
--- a/base/strings/utf_string_conversion_utils.cc
+++ b/base/strings/utf_string_conversion_utils.cc
@@ -12,11 +12,12 @@
 // ReadUnicodeCharacter --------------------------------------------------------
 
 bool ReadUnicodeCharacter(const char* src,
-                          int32_t src_len,
-                          int32_t* char_index,
+                          size_t src_len,
+                          size_t* char_index,
                           base_icu::UChar32* code_point_out) {
   base_icu::UChar32 code_point;
-  CBU8_NEXT(src, *char_index, src_len, code_point);
+  CBU8_NEXT(reinterpret_cast<const uint8_t*>(src), *char_index, src_len,
+            code_point);
   *code_point_out = code_point;
 
   // The ICU macro above moves to the next char, we want to point to the last
@@ -28,13 +29,12 @@
 }
 
 bool ReadUnicodeCharacter(const char16_t* src,
-                          int32_t src_len,
-                          int32_t* char_index,
+                          size_t src_len,
+                          size_t* char_index,
                           base_icu::UChar32* code_point) {
   if (CBU16_IS_SURROGATE(src[*char_index])) {
-    if (!CBU16_IS_SURROGATE_LEAD(src[*char_index]) ||
-        *char_index + 1 >= src_len ||
-        !CBU16_IS_TRAIL(src[*char_index + 1])) {
+    if (!CBU16_IS_SURROGATE_LEAD(src[*char_index]) || !src_len ||
+        *char_index >= src_len - 1 || !CBU16_IS_TRAIL(src[*char_index + 1])) {
       // Invalid surrogate pair.
       return false;
     }
@@ -53,8 +53,8 @@
 
 #if defined(WCHAR_T_IS_UTF32)
 bool ReadUnicodeCharacter(const wchar_t* src,
-                          int32_t src_len,
-                          int32_t* char_index,
+                          size_t src_len,
+                          size_t* char_index,
                           base_icu::UChar32* code_point) {
   // Conversion is easy since the source is 32-bit.
   *code_point = src[*char_index];
@@ -66,20 +66,21 @@
 
 // WriteUnicodeCharacter -------------------------------------------------------
 
-size_t WriteUnicodeCharacter(uint32_t code_point, std::string* output) {
-  if (code_point <= 0x7f) {
+size_t WriteUnicodeCharacter(base_icu::UChar32 code_point,
+                             std::string* output) {
+  if (code_point >= 0 && code_point <= 0x7f) {
     // Fast path the common case of one byte.
     output->push_back(static_cast<char>(code_point));
     return 1;
   }
 
-
   // CBU8_APPEND_UNSAFE can append up to 4 bytes.
   size_t char_offset = output->length();
   size_t original_char_offset = char_offset;
   output->resize(char_offset + CBU8_MAX_LENGTH);
 
-  CBU8_APPEND_UNSAFE(&(*output)[0], char_offset, code_point);
+  CBU8_APPEND_UNSAFE(reinterpret_cast<uint8_t*>(output->data()), char_offset,
+                     code_point);
 
   // CBU8_APPEND_UNSAFE will advance our pointer past the inserted character, so
   // it will represent the new length of the string.
@@ -87,9 +88,10 @@
   return char_offset - original_char_offset;
 }
 
-size_t WriteUnicodeCharacter(uint32_t code_point, std::u16string* output) {
+size_t WriteUnicodeCharacter(base_icu::UChar32 code_point,
+                             std::u16string* output) {
   if (CBU16_LENGTH(code_point) == 1) {
-    // Thie code point is in the Basic Multilingual Plane (BMP).
+    // The code point is in the Basic Multilingual Plane (BMP).
     output->push_back(static_cast<char16_t>(code_point));
     return 1;
   }
diff --git a/base/strings/utf_string_conversion_utils.h b/base/strings/utf_string_conversion_utils.h
index 877d264..8c209a2 100644
--- a/base/strings/utf_string_conversion_utils.h
+++ b/base/strings/utf_string_conversion_utils.h
@@ -49,21 +49,21 @@
 //
 // Returns true on success. On false, |*code_point| will be invalid.
 BASE_EXPORT bool ReadUnicodeCharacter(const char* src,
-                                      int32_t src_len,
-                                      int32_t* char_index,
+                                      size_t src_len,
+                                      size_t* char_index,
                                       base_icu::UChar32* code_point_out);
 
 // Reads a UTF-16 character. The usage is the same as the 8-bit version above.
 BASE_EXPORT bool ReadUnicodeCharacter(const char16_t* src,
-                                      int32_t src_len,
-                                      int32_t* char_index,
+                                      size_t src_len,
+                                      size_t* char_index,
                                       base_icu::UChar32* code_point);
 
 #if defined(WCHAR_T_IS_UTF32)
 // Reads UTF-32 character. The usage is the same as the 8-bit version above.
 BASE_EXPORT bool ReadUnicodeCharacter(const wchar_t* src,
-                                      int32_t src_len,
-                                      int32_t* char_index,
+                                      size_t src_len,
+                                      size_t* char_index,
                                       base_icu::UChar32* code_point);
 #endif  // defined(WCHAR_T_IS_UTF32)
 
@@ -71,20 +71,21 @@
 
 // Appends a UTF-8 character to the given 8-bit string.  Returns the number of
 // bytes written.
-BASE_EXPORT size_t WriteUnicodeCharacter(uint32_t code_point,
+BASE_EXPORT size_t WriteUnicodeCharacter(base_icu::UChar32 code_point,
                                          std::string* output);
 
 // Appends the given code point as a UTF-16 character to the given 16-bit
 // string.  Returns the number of 16-bit values written.
-BASE_EXPORT size_t WriteUnicodeCharacter(uint32_t code_point,
+BASE_EXPORT size_t WriteUnicodeCharacter(base_icu::UChar32 code_point,
                                          std::u16string* output);
 
 #if defined(WCHAR_T_IS_UTF32)
 // Appends the given UTF-32 character to the given 32-bit string.  Returns the
 // number of 32-bit values written.
-inline size_t WriteUnicodeCharacter(uint32_t code_point, std::wstring* output) {
+inline size_t WriteUnicodeCharacter(base_icu::UChar32 code_point,
+                                    std::wstring* output) {
   // This is the easy case, just append the character.
-  output->push_back(code_point);
+  output->push_back(static_cast<wchar_t>(code_point));
   return 1;
 }
 #endif  // defined(WCHAR_T_IS_UTF32)
diff --git a/base/third_party/icu/icu_utf.h b/base/third_party/icu/icu_utf.h
index 16792c4..0b50b71 100644
--- a/base/third_party/icu/icu_utf.h
+++ b/base/third_party/icu/icu_utf.h
@@ -118,7 +118,7 @@
  * @return TRUE or FALSE
  * @stable ICU 2.4
  */
-#define CBU_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800)
+#define CBU_IS_SURROGATE(c) (((uint32_t)(c)&0xfffff800) == 0xd800)
 
 /**
  * Assuming c is a surrogate code point (U_IS_SURROGATE(c)),
@@ -278,25 +278,27 @@
  * @see U8_APPEND
  * @stable ICU 2.4
  */
-#define CBU8_APPEND_UNSAFE(s, i, c) CBUPRV_BLOCK_MACRO_BEGIN { \
-    uint32_t __uc=(c); \
-    if(__uc<=0x7f) { \
-        (s)[(i)++]=(uint8_t)__uc; \
-    } else { \
-        if(__uc<=0x7ff) { \
-            (s)[(i)++]=(uint8_t)((__uc>>6)|0xc0); \
-        } else { \
-            if(__uc<=0xffff) { \
-                (s)[(i)++]=(uint8_t)((__uc>>12)|0xe0); \
-            } else { \
-                (s)[(i)++]=(uint8_t)((__uc>>18)|0xf0); \
-                (s)[(i)++]=(uint8_t)(((__uc>>12)&0x3f)|0x80); \
-            } \
-            (s)[(i)++]=(uint8_t)(((__uc>>6)&0x3f)|0x80); \
-        } \
-        (s)[(i)++]=(uint8_t)((__uc&0x3f)|0x80); \
-    } \
-} CBUPRV_BLOCK_MACRO_END
+#define CBU8_APPEND_UNSAFE(s, i, c)                             \
+  CBUPRV_BLOCK_MACRO_BEGIN {                                    \
+    uint32_t __uc = (uint32_t)(c);                              \
+    if (__uc <= 0x7f) {                                         \
+      (s)[(i)++] = (uint8_t)__uc;                               \
+    } else {                                                    \
+      if (__uc <= 0x7ff) {                                      \
+        (s)[(i)++] = (uint8_t)((__uc >> 6) | 0xc0);             \
+      } else {                                                  \
+        if (__uc <= 0xffff) {                                   \
+          (s)[(i)++] = (uint8_t)((__uc >> 12) | 0xe0);          \
+        } else {                                                \
+          (s)[(i)++] = (uint8_t)((__uc >> 18) | 0xf0);          \
+          (s)[(i)++] = (uint8_t)(((__uc >> 12) & 0x3f) | 0x80); \
+        }                                                       \
+        (s)[(i)++] = (uint8_t)(((__uc >> 6) & 0x3f) | 0x80);    \
+      }                                                         \
+      (s)[(i)++] = (uint8_t)((__uc & 0x3f) | 0x80);             \
+    }                                                           \
+  }                                                             \
+  CBUPRV_BLOCK_MACRO_END
 
 // source/common/unicode/utf16.h
 
@@ -314,7 +316,7 @@
  * @return TRUE or FALSE
  * @stable ICU 2.4
  */
-#define CBU16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800)
+#define CBU16_IS_LEAD(c) (((uint32_t)(c)&0xfffffc00) == 0xd800)
 
 /**
  * Is this code unit a trail surrogate (U+dc00..U+dfff)?
@@ -322,7 +324,7 @@
  * @return TRUE or FALSE
  * @stable ICU 2.4
  */
-#define CBU16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00)
+#define CBU16_IS_TRAIL(c) (((uint32_t)(c)&0xfffffc00) == 0xdc00)
 
 /**
  * Is this code unit a surrogate (U+d800..U+dfff)?
diff --git a/copy.bara.sky b/copy.bara.sky
index b1d8df5..a0c899b 100644
--- a/copy.bara.sky
+++ b/copy.bara.sky
@@ -27,6 +27,8 @@
         "base/i18n/uchar.h",
         "base/memory/raw_ptr.h",
         "base/memory/raw_ptr_exclusion.h",
+        "base/numerics/safe_conversions.h",
+        "base/numerics/safe_conversions_impl.h",
         "base/no_destructor.h",
         "base/ranges/*.h",
         "base/stl_util.h",
diff --git a/url/gurl.h b/url/gurl.h
index 10ba992..97a60ab 100644
--- a/url/gurl.h
+++ b/url/gurl.h
@@ -470,14 +470,16 @@
 
   // Returns the substring of the input identified by the given component.
   std::string ComponentString(const url::Component& comp) const {
-    if (comp.len <= 0)
+    if (!comp.is_nonempty())
       return std::string();
-    return std::string(spec_, comp.begin, comp.len);
+    return std::string(spec_, static_cast<size_t>(comp.begin),
+                       static_cast<size_t>(comp.len));
   }
   gurl_base::StringPiece ComponentStringPiece(const url::Component& comp) const {
-    if (comp.len <= 0)
+    if (!comp.is_nonempty())
       return gurl_base::StringPiece();
-    return gurl_base::StringPiece(&spec_[comp.begin], comp.len);
+    return gurl_base::StringPiece(&spec_[static_cast<size_t>(comp.begin)],
+                             static_cast<size_t>(comp.len));
   }
 
   void ProcessFileSystemURLAfterReplaceComponents();
diff --git a/url/url_canon_etc.cc b/url/url_canon_etc.cc
index b45cea0..c3ebddd 100644
--- a/url/url_canon_etc.cc
+++ b/url/url_canon_etc.cc
@@ -101,7 +101,7 @@
               const Component& scheme,
               CanonOutput* output,
               Component* out_scheme) {
-  if (scheme.len <= 0) {
+  if (!scheme.is_nonempty()) {
     // Scheme is unspecified or empty, convert to empty by appending a colon.
     *out_scheme = Component(output->length(), 0);
     output->push_back(':');
@@ -117,12 +117,13 @@
   // FindAndCompareScheme, which could cause some security checks on
   // schemes to be incorrect.
   bool success = true;
-  int end = scheme.end();
-  for (int i = scheme.begin; i < end; i++) {
+  size_t begin = static_cast<size_t>(scheme.begin);
+  size_t end = static_cast<size_t>(scheme.end());
+  for (size_t i = begin; i < end; i++) {
     UCHAR ch = static_cast<UCHAR>(spec[i]);
     char replacement = 0;
     if (ch < 0x80) {
-      if (i == scheme.begin) {
+      if (i == begin) {
         // Need to do a special check for the first letter of the scheme.
         if (IsSchemeFirstChar(static_cast<unsigned char>(ch)))
           replacement = kSchemeCanonical[ch];
@@ -179,8 +180,9 @@
   out_username->begin = output->length();
   if (username.len > 0) {
     // This will escape characters not valid for the username.
-    AppendStringOfType(&username_spec[username.begin], username.len,
-                       CHAR_USERINFO, output);
+    AppendStringOfType(&username_spec[username.begin],
+                       static_cast<size_t>(username.len), CHAR_USERINFO,
+                       output);
   }
   out_username->len = output->length() - out_username->begin;
 
@@ -189,8 +191,9 @@
   if (password.len > 0) {
     output->push_back(':');
     out_password->begin = output->length();
-    AppendStringOfType(&password_spec[password.begin], password.len,
-                       CHAR_USERINFO, output);
+    AppendStringOfType(&password_spec[password.begin],
+                       static_cast<size_t>(password.len), CHAR_USERINFO,
+                       output);
     out_password->len = output->length() - out_password->begin;
   } else {
     *out_password = Component();
@@ -223,7 +226,8 @@
     // what the error was, and mark the URL as invalid by returning false.
     output->push_back(':');
     out_port->begin = output->length();
-    AppendInvalidNarrowString(spec, port.begin, port.end(), output);
+    AppendInvalidNarrowString(spec, static_cast<size_t>(port.begin),
+                              static_cast<size_t>(port.end()), output);
     out_port->len = output->length() - out_port->begin;
     return false;
   }
@@ -285,7 +289,7 @@
                        const Component& ref,
                        CanonOutput* output,
                        Component* out_ref) {
-  if (ref.len < 0) {
+  if (!ref.is_valid()) {
     // Common case of no ref.
     *out_ref = Component();
     return;
@@ -297,8 +301,8 @@
   out_ref->begin = output->length();
 
   // Now iterate through all the characters, converting to UTF-8 and validating.
-  int end = ref.end();
-  for (int i = ref.begin; i < end; i++) {
+  size_t end = static_cast<size_t>(ref.end());
+  for (size_t i = static_cast<size_t>(ref.begin); i < end; i++) {
     UCHAR current_char = static_cast<UCHAR>(spec[i]);
     if (current_char < 0x80) {
       if (kShouldEscapeCharInFragment[current_char])
diff --git a/url/url_canon_host.cc b/url/url_canon_host.cc
index 370dd77..edc9d67 100644
--- a/url/url_canon_host.cc
+++ b/url/url_canon_host.cc
@@ -123,15 +123,15 @@
 //    |*has_non_ascii| flag.
 //
 // The return value indicates if the output is a potentially valid host name.
-template<typename INCHAR, typename OUTCHAR>
+template <typename INCHAR, typename OUTCHAR>
 bool DoSimpleHost(const INCHAR* host,
-                  int host_len,
+                  size_t host_len,
                   CanonOutputT<OUTCHAR>* output,
                   bool* has_non_ascii) {
   *has_non_ascii = false;
 
   bool success = true;
-  for (int i = 0; i < host_len; ++i) {
+  for (size_t i = 0; i < host_len; ++i) {
     unsigned int source = host[i];
     if (source == '%') {
       // Unescape first, if possible.
@@ -175,7 +175,7 @@
 }
 
 // Canonicalizes a host that requires IDN conversion. Returns true on success
-bool DoIDNHost(const char16_t* src, int src_len, CanonOutput* output) {
+bool DoIDNHost(const char16_t* src, size_t src_len, CanonOutput* output) {
   int original_output_len = output->length();  // So we can rewind below.
 
   // We need to escape URL before doing IDN conversion, since punicode strings
@@ -202,8 +202,8 @@
   // unescaping. Although we unescaped everything before this function call, if
   // somebody does %00 as fullwidth, ICU will convert this to ASCII.
   bool success = DoSimpleHost(wide_output.data(),
-                              wide_output.length(),
-                              output, &has_non_ascii);
+                              static_cast<size_t>(wide_output.length()), output,
+                              &has_non_ascii);
   if (has_non_ascii) {
     // ICU generated something that DoSimpleHost didn't think looked like
     // ASCII. This is quite rare, but ICU might convert some characters to
@@ -220,7 +220,8 @@
     // ASCII isn't strictly necessary, but DoSimpleHost handles this case
     // anyway so we handle it/
     output->set_length(original_output_len);
-    AppendInvalidNarrowString(wide_output.data(), 0, wide_output.length(),
+    AppendInvalidNarrowString(wide_output.data(), 0,
+                              static_cast<size_t>(wide_output.length()),
                               output);
     return false;
   }
@@ -230,8 +231,11 @@
 // 8-bit convert host to its ASCII version: this converts the UTF-8 input to
 // UTF-16. The has_escaped flag should be set if the input string requires
 // unescaping.
-bool DoComplexHost(const char* host, int host_len,
-                   bool has_non_ascii, bool has_escaped, CanonOutput* output) {
+bool DoComplexHost(const char* host,
+                   size_t host_len,
+                   bool has_non_ascii,
+                   bool has_escaped,
+                   CanonOutput* output) {
   // Save the current position in the output. We may write stuff and rewind it
   // below, so we need to know where to rewind to.
   int begin_length = output->length();
@@ -239,7 +243,7 @@
   // Points to the UTF-8 data we want to convert. This will either be the
   // input or the unescaped version written to |*output| if necessary.
   const char* utf8_source;
-  int utf8_source_len;
+  size_t utf8_source_len;
   bool are_all_escaped_valid = true;
   if (has_escaped) {
     // Unescape before converting to UTF-16 for IDN. We write this into the
@@ -264,7 +268,7 @@
     // Save the pointer into the data was just converted (it may be appended to
     // other data in the output buffer).
     utf8_source = &output->data()[begin_length];
-    utf8_source_len = output->length() - begin_length;
+    utf8_source_len = static_cast<size_t>(output->length() - begin_length);
   } else {
     // We don't need to unescape, use input for IDNization later. (We know the
     // input has non-ASCII, or the simple version would have been called
@@ -280,17 +284,18 @@
   if (!ConvertUTF8ToUTF16(utf8_source, utf8_source_len, &utf16)) {
     // In this error case, the input may or may not be the output.
     StackBuffer utf8;
-    for (int i = 0; i < utf8_source_len; i++)
+    for (size_t i = 0; i < utf8_source_len; i++)
       utf8.push_back(utf8_source[i]);
     output->set_length(begin_length);
-    AppendInvalidNarrowString(utf8.data(), 0, utf8.length(), output);
+    AppendInvalidNarrowString(utf8.data(), 0,
+                              static_cast<size_t>(utf8.length()), output);
     return false;
   }
   output->set_length(begin_length);
 
   // This will call DoSimpleHost which will do normal ASCII canonicalization
   // and also check for IP addresses in the outpt.
-  return DoIDNHost(utf16.data(), utf16.length(), output) &&
+  return DoIDNHost(utf16.data(), static_cast<size_t>(utf16.length()), output) &&
          are_all_escaped_valid;
 }
 
@@ -298,7 +303,7 @@
 // the backend, so we just pass through. The has_escaped flag should be set if
 // the input string requires unescaping.
 bool DoComplexHost(const char16_t* host,
-                   int host_len,
+                   size_t host_len,
                    bool has_non_ascii,
                    bool has_escaped,
                    CanonOutput* output) {
@@ -319,8 +324,8 @@
 
     // Once we convert to UTF-8, we can use the 8-bit version of the complex
     // host handling code above.
-    return DoComplexHost(utf8.data(), utf8.length(), has_non_ascii,
-                         has_escaped, output);
+    return DoComplexHost(utf8.data(), static_cast<size_t>(utf8.length()),
+                         has_non_ascii, has_escaped, output);
   }
 
   // No unescaping necessary, we can safely pass the input to ICU. This
@@ -334,16 +339,18 @@
 bool DoHostSubstring(const CHAR* spec,
                      const Component& host,
                      CanonOutput* output) {
+  GURL_DCHECK(host.is_valid());
+
   bool has_non_ascii, has_escaped;
   ScanHostname<CHAR, UCHAR>(spec, host, &has_non_ascii, &has_escaped);
 
   if (has_non_ascii || has_escaped) {
-    return DoComplexHost(&spec[host.begin], host.len, has_non_ascii,
-                         has_escaped, output);
+    return DoComplexHost(&spec[host.begin], static_cast<size_t>(host.len),
+                         has_non_ascii, has_escaped, output);
   }
 
-  const bool success =
-      DoSimpleHost(&spec[host.begin], host.len, output, &has_non_ascii);
+  const bool success = DoSimpleHost(
+      &spec[host.begin], static_cast<size_t>(host.len), output, &has_non_ascii);
   GURL_DCHECK(!has_non_ascii);
   return success;
 }
@@ -353,7 +360,7 @@
             const Component& host,
             CanonOutput* output,
             CanonHostInfo* host_info) {
-  if (host.len <= 0) {
+  if (!host.is_nonempty()) {
     // Empty hosts don't need anything.
     host_info->family = CanonHostInfo::NEUTRAL;
     host_info->out_host = Component();
diff --git a/url/url_canon_internal.cc b/url/url_canon_internal.cc
index bbb27a0..f6b4b03 100644
--- a/url/url_canon_internal.cc
+++ b/url/url_canon_internal.cc
@@ -11,17 +11,19 @@
 #include <cstdio>
 #include <string>
 
+#include "base/numerics/safe_conversions.h"
 #include "base/strings/utf_string_conversion_utils.h"
 
 namespace url {
 
 namespace {
 
-template<typename CHAR, typename UCHAR>
-void DoAppendStringOfType(const CHAR* source, int length,
+template <typename CHAR, typename UCHAR>
+void DoAppendStringOfType(const CHAR* source,
+                          size_t length,
                           SharedCharTypes type,
                           CanonOutput* output) {
-  for (int i = 0; i < length; i++) {
+  for (size_t i = 0; i < length; i++) {
     if (static_cast<UCHAR>(source[i]) >= 0x80) {
       // ReadChar will fill the code point with kUnicodeReplacementCharacter
       // when the input is invalid, which is what we want.
@@ -41,10 +43,12 @@
 
 // This function assumes the input values are all contained in 8-bit,
 // although it allows any type. Returns true if input is valid, false if not.
-template<typename CHAR, typename UCHAR>
-void DoAppendInvalidNarrowString(const CHAR* spec, int begin, int end,
+template <typename CHAR, typename UCHAR>
+void DoAppendInvalidNarrowString(const CHAR* spec,
+                                 size_t begin,
+                                 size_t end,
                                  CanonOutput* output) {
-  for (int i = begin; i < end; i++) {
+  for (size_t i = begin; i < end; i++) {
     UCHAR uch = static_cast<UCHAR>(spec[i]);
     if (uch >= 0x80) {
       // Handle UTF-8/16 encodings. This call will correctly handle the error
@@ -98,7 +102,8 @@
       // Convert to UTF-8.
       dest_component->begin = utf8_buffer->length();
       success = ConvertUTF16ToUTF8(&override_source[override_component.begin],
-                                   override_component.len, utf8_buffer);
+                                   static_cast<size_t>(override_component.len),
+                                   utf8_buffer);
       dest_component->len = utf8_buffer->length() - dest_component->begin;
     }
   }
@@ -235,26 +240,24 @@
 
 const base_icu::UChar32 kUnicodeReplacementCharacter = 0xfffd;
 
-void AppendStringOfType(const char* source, int length,
+void AppendStringOfType(const char* source,
+                        size_t length,
                         SharedCharTypes type,
                         CanonOutput* output) {
   DoAppendStringOfType<char, unsigned char>(source, length, type, output);
 }
 
 void AppendStringOfType(const char16_t* source,
-                        int length,
+                        size_t length,
                         SharedCharTypes type,
                         CanonOutput* output) {
   DoAppendStringOfType<char16_t, char16_t>(source, length, type, output);
 }
 
 bool ReadUTFChar(const char* str,
-                 int* begin,
-                 int length,
+                 size_t* begin,
+                 size_t length,
                  base_icu::UChar32* code_point_out) {
-  // This depends on ints and int32s being the same thing. If they're not, it
-  // will fail to compile.
-  // TODO(mmenke): This should probably be fixed.
   if (!gurl_base::ReadUnicodeCharacter(str, length, begin, code_point_out) ||
       !gurl_base::IsValidCharacter(*code_point_out)) {
     *code_point_out = kUnicodeReplacementCharacter;
@@ -264,12 +267,9 @@
 }
 
 bool ReadUTFChar(const char16_t* str,
-                 int* begin,
-                 int length,
+                 size_t* begin,
+                 size_t length,
                  base_icu::UChar32* code_point_out) {
-  // This depends on ints and int32s being the same thing. If they're not, it
-  // will fail to compile.
-  // TODO(mmenke): This should probably be fixed.
   if (!gurl_base::ReadUnicodeCharacter(str, length, begin, code_point_out) ||
       !gurl_base::IsValidCharacter(*code_point_out)) {
     *code_point_out = kUnicodeReplacementCharacter;
@@ -278,23 +278,25 @@
   return true;
 }
 
-void AppendInvalidNarrowString(const char* spec, int begin, int end,
+void AppendInvalidNarrowString(const char* spec,
+                               size_t begin,
+                               size_t end,
                                CanonOutput* output) {
   DoAppendInvalidNarrowString<char, unsigned char>(spec, begin, end, output);
 }
 
 void AppendInvalidNarrowString(const char16_t* spec,
-                               int begin,
-                               int end,
+                               size_t begin,
+                               size_t end,
                                CanonOutput* output) {
   DoAppendInvalidNarrowString<char16_t, char16_t>(spec, begin, end, output);
 }
 
 bool ConvertUTF16ToUTF8(const char16_t* input,
-                        int input_len,
+                        size_t input_len,
                         CanonOutput* output) {
   bool success = true;
-  for (int i = 0; i < input_len; i++) {
+  for (size_t i = 0; i < input_len; i++) {
     base_icu::UChar32 code_point;
     success &= ReadUTFChar(input, &i, input_len, &code_point);
     AppendUTF8Value(code_point, output);
@@ -303,10 +305,10 @@
 }
 
 bool ConvertUTF8ToUTF16(const char* input,
-                        int input_len,
+                        size_t input_len,
                         CanonOutputT<char16_t>* output) {
   bool success = true;
-  for (int i = 0; i < input_len; i++) {
+  for (size_t i = 0; i < input_len; i++) {
     base_icu::UChar32 code_point;
     success &= ReadUTFChar(input, &i, input_len, &code_point);
     AppendUTF16Value(code_point, output);
diff --git a/url/url_canon_internal.h b/url/url_canon_internal.h
index 807ddc5..a41a771 100644
--- a/url/url_canon_internal.h
+++ b/url/url_canon_internal.h
@@ -77,11 +77,12 @@
 
 // Appends the given string to the output, escaping characters that do not
 // match the given |type| in SharedCharTypes.
-void AppendStringOfType(const char* source, int length,
+void AppendStringOfType(const char* source,
+                        size_t length,
                         SharedCharTypes type,
                         CanonOutput* output);
 void AppendStringOfType(const char16_t* source,
-                        int length,
+                        size_t length,
                         SharedCharTypes type,
                         CanonOutput* output);
 
@@ -107,8 +108,8 @@
 // Indicates if the given character is a dot or dot equivalent, returning the
 // number of characters taken by it. This will be one for a literal dot, 3 for
 // an escaped dot. If the character is not a dot, this will return 0.
-template<typename CHAR>
-inline int IsDot(const CHAR* spec, int offset, int end) {
+template <typename CHAR>
+inline size_t IsDot(const CHAR* spec, size_t offset, size_t end) {
   if (spec[offset] == '.') {
     return 1;
   } else if (spec[offset] == '%' && offset + 3 <= end &&
@@ -154,8 +155,8 @@
 // (for a single-byte ASCII character, it will not be changed).
 COMPONENT_EXPORT(URL)
 bool ReadUTFChar(const char* str,
-                 int* begin,
-                 int length,
+                 size_t* begin,
+                 size_t length,
                  base_icu::UChar32* code_point_out);
 
 // Generic To-UTF-8 converter. This will call the given append method for each
@@ -231,8 +232,8 @@
 // (for a single-16-bit-word character, it will not be changed).
 COMPONENT_EXPORT(URL)
 bool ReadUTFChar(const char16_t* str,
-                 int* begin,
-                 int length,
+                 size_t* begin,
+                 size_t length,
                  base_icu::UChar32* code_point_out);
 
 // Equivalent to U16_APPEND_UNSAFE in ICU but uses our output method.
@@ -268,8 +269,8 @@
 // Assumes that ch[begin] is within range in the array, but does not assume
 // that any following characters are.
 inline bool AppendUTF8EscapedChar(const char16_t* str,
-                                  int* begin,
-                                  int length,
+                                  size_t* begin,
+                                  size_t length,
                                   CanonOutput* output) {
   // UTF-16 input. ReadUTFChar will handle invalid characters for us and give
   // us the kUnicodeReplacementCharacter, so we don't have to do special
@@ -281,7 +282,9 @@
 }
 
 // Handles UTF-8 input. See the wide version above for usage.
-inline bool AppendUTF8EscapedChar(const char* str, int* begin, int length,
+inline bool AppendUTF8EscapedChar(const char* str,
+                                  size_t* begin,
+                                  size_t length,
                                   CanonOutput* output) {
   // ReadUTF8Char will handle invalid characters for us and give us the
   // kUnicodeReplacementCharacter, so we don't have to do special checking
@@ -308,8 +311,10 @@
   return c <= 255;
 }
 
-template<typename CHAR>
-inline bool DecodeEscaped(const CHAR* spec, int* begin, int end,
+template <typename CHAR>
+inline bool DecodeEscaped(const CHAR* spec,
+                          size_t* begin,
+                          size_t end,
                           unsigned char* unescaped_value) {
   if (*begin + 3 > end ||
       !Is8BitChar(spec[*begin + 1]) || !Is8BitChar(spec[*begin + 2])) {
@@ -338,11 +343,13 @@
 // This is used in error cases to append invalid output so that it looks
 // approximately correct. Non-error cases should not call this function since
 // the escaping rules are not guaranteed!
-void AppendInvalidNarrowString(const char* spec, int begin, int end,
+void AppendInvalidNarrowString(const char* spec,
+                               size_t begin,
+                               size_t end,
                                CanonOutput* output);
 void AppendInvalidNarrowString(const char16_t* spec,
-                               int begin,
-                               int end,
+                               size_t begin,
+                               size_t end,
                                CanonOutput* output);
 
 // Misc canonicalization helpers ----------------------------------------------
@@ -357,11 +364,11 @@
 // normal.
 COMPONENT_EXPORT(URL)
 bool ConvertUTF16ToUTF8(const char16_t* input,
-                        int input_len,
+                        size_t input_len,
                         CanonOutput* output);
 COMPONENT_EXPORT(URL)
 bool ConvertUTF8ToUTF16(const char* input,
-                        int input_len,
+                        size_t input_len,
                         CanonOutputT<char16_t>* output);
 
 // Converts from UTF-16 to 8-bit using the character set converter. If the
diff --git a/url/url_canon_mailtourl.cc b/url/url_canon_mailtourl.cc
index f4fe2b4..ff62bea 100644
--- a/url/url_canon_mailtourl.cc
+++ b/url/url_canon_mailtourl.cc
@@ -57,8 +57,8 @@
     // Copy the path using path URL's more lax escaping rules.
     // We convert to UTF-8 and escape non-ASCII, but leave most
     // ASCII characters alone.
-    int end = parsed.path.end();
-    for (int i = parsed.path.begin; i < end; ++i) {
+    size_t end = static_cast<size_t>(parsed.path.end());
+    for (size_t i = static_cast<size_t>(parsed.path.begin); i < end; ++i) {
       UCHAR uch = static_cast<UCHAR>(source.path[i]);
       if (ShouldEncodeMailboxCharacter<UCHAR>(uch))
         success &= AppendUTF8EscapedChar(source.path, &i, end, output);
diff --git a/url/url_canon_path.cc b/url/url_canon_path.cc
index e043043..32cb5f3 100644
--- a/url/url_canon_path.cc
+++ b/url/url_canon_path.cc
@@ -101,9 +101,11 @@
 // If the input is "../foo", |after_dot| = 1, |end| = 6, and
 // at the end, |*consumed_len| = 2 for the "./" this function consumed. The
 // original dot length should be handled by the caller.
-template<typename CHAR>
-DotDisposition ClassifyAfterDot(const CHAR* spec, int after_dot,
-                                int end, int* consumed_len) {
+template <typename CHAR>
+DotDisposition ClassifyAfterDot(const CHAR* spec,
+                                size_t after_dot,
+                                size_t end,
+                                size_t* consumed_len) {
   if (after_dot == end) {
     // Single dot at the end.
     *consumed_len = 0;
@@ -115,9 +117,9 @@
     return DIRECTORY_CUR;
   }
 
-  int second_dot_len = IsDot(spec, after_dot, end);
+  size_t second_dot_len = IsDot(spec, after_dot, end);
   if (second_dot_len) {
-    int after_second_dot = after_dot + second_dot_len;
+    size_t after_second_dot = after_dot + second_dot_len;
     if (after_second_dot == end) {
       // Double dot at the end.
       *consumed_len = second_dot_len;
@@ -193,10 +195,10 @@
 // ends with a '%' followed by one or two characters, and the '%' is the one
 // pointed to by |last_invalid_percent_index|.  The last character in the string
 // was just unescaped.
-template<typename CHAR>
+template <typename CHAR>
 void CheckForNestedEscapes(const CHAR* spec,
-                           int next_input_index,
-                           int input_len,
+                           size_t next_input_index,
+                           size_t input_len,
                            int last_invalid_percent_index,
                            CanonOutput* output) {
   const int length = output->length();
@@ -218,9 +220,10 @@
   }
 
   // Now output ends like "%cc".  Try to unescape this.
-  int begin = last_invalid_percent_index;
+  size_t begin = static_cast<size_t>(last_invalid_percent_index);
   unsigned char temp;
-  if (DecodeEscaped(output->data(), &begin, output->length(), &temp)) {
+  if (DecodeEscaped(output->data(), &begin,
+                    static_cast<size_t>(output->length()), &temp)) {
     // New escape sequence found.  Overwrite the characters following the '%'
     // with "25", and push_back() the one or two characters that were following
     // the '%' when we were called.
@@ -252,7 +255,10 @@
                            const Component& path,
                            int path_begin_in_output,
                            CanonOutput* output) {
-  int end = path.end();
+  if (!path.is_nonempty())
+    return true;
+
+  size_t end = static_cast<size_t>(path.end());
 
   // We use this variable to minimize the amount of work done when unescaping --
   // we'll only call CheckForNestedEscapes() when this points at one of the last
@@ -260,7 +266,7 @@
   int last_invalid_percent_index = INT_MIN;
 
   bool success = true;
-  for (int i = path.begin; i < end; i++) {
+  for (size_t i = static_cast<size_t>(path.begin); i < end; i++) {
     GURL_DCHECK_LT(last_invalid_percent_index, output->length());
     UCHAR uch = static_cast<UCHAR>(spec[i]);
     if (sizeof(CHAR) > 1 && uch >= 0x80) {
@@ -276,7 +282,7 @@
       unsigned char flags = kPathCharLookup[out_ch];
       if (flags & SPECIAL) {
         // Needs special handling of some sort.
-        int dotlen;
+        size_t dotlen;
         if ((dotlen = IsDot(spec, i, end)) > 0) {
           // See if this dot was preceded by a slash in the output.
           //
@@ -287,7 +293,7 @@
           if (output->length() > path_begin_in_output &&
               output->at(output->length() - 1) == '/') {
             // Slash followed by a dot, check to see if this is means relative
-            int consumed_len;
+            size_t consumed_len;
             switch (ClassifyAfterDot<CHAR>(spec, i + dotlen, end,
                                            &consumed_len)) {
               case NOT_A_DIRECTORY:
diff --git a/url/url_canon_pathurl.cc b/url/url_canon_pathurl.cc
index e726cfb..d8d65f3 100644
--- a/url/url_canon_pathurl.cc
+++ b/url/url_canon_pathurl.cc
@@ -32,8 +32,8 @@
     // https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state
     // https://url.spec.whatwg.org/#c0-control-percent-encode-set
     new_component->begin = output->length();
-    int end = component.end();
-    for (int i = component.begin; i < end; i++) {
+    size_t end = static_cast<size_t>(component.end());
+    for (size_t i = static_cast<size_t>(component.begin); i < end; i++) {
       UCHAR uch = static_cast<UCHAR>(source[i]);
       if (uch < 0x20 || uch > 0x7E)
         AppendUTF8EscapedChar(source, &i, end, output);
diff --git a/url/url_canon_query.cc b/url/url_canon_query.cc
index b3a1118..53699c5 100644
--- a/url/url_canon_query.cc
+++ b/url/url_canon_query.cc
@@ -72,10 +72,12 @@
                   const Component& query,
                   CharsetConverter* converter,
                   CanonOutput* output) {
+  GURL_DCHECK(query.is_valid());
   // This function will replace any misencoded values with the invalid
   // character. This is what we want so we don't have to check for error.
   RawCanonOutputW<1024> utf16;
-  ConvertUTF8ToUTF16(&spec[query.begin], query.len, &utf16);
+  ConvertUTF8ToUTF16(&spec[query.begin], static_cast<size_t>(query.len),
+                     &utf16);
   converter->ConvertFromUTF16(utf16.data(), utf16.length(), output);
 }
 
@@ -86,7 +88,9 @@
                   const Component& query,
                   CharsetConverter* converter,
                   CanonOutput* output) {
-  converter->ConvertFromUTF16(&spec[query.begin], query.len, output);
+  GURL_DCHECK(query.is_valid());
+  converter->ConvertFromUTF16(&spec[query.begin],
+                              static_cast<size_t>(query.len), output);
 }
 
 template<typename CHAR, typename UCHAR>
@@ -109,7 +113,8 @@
 
     } else {
       // No converter, do our own UTF-8 conversion.
-      AppendStringOfType(&spec[query.begin], query.len, CHAR_QUERY, output);
+      AppendStringOfType(&spec[query.begin], static_cast<size_t>(query.len),
+                         CHAR_QUERY, output);
     }
   }
 }
diff --git a/url/url_canon_unittest.cc b/url/url_canon_unittest.cc
index 0170e00..4fa31ec 100644
--- a/url/url_canon_unittest.cc
+++ b/url/url_canon_unittest.cc
@@ -173,9 +173,9 @@
       out_str.clear();
       StdStringCanonOutput output(&out_str);
 
-      int input_len = static_cast<int>(strlen(utf_cases[i].input8));
+      size_t input_len = strlen(utf_cases[i].input8);
       bool success = true;
-      for (int ch = 0; ch < input_len; ch++) {
+      for (size_t ch = 0; ch < input_len; ch++) {
         success &= AppendUTF8EscapedChar(utf_cases[i].input8, &ch, input_len,
                                          &output);
       }
@@ -189,9 +189,9 @@
 
       std::u16string input_str(
           test_utils::TruncateWStringToUTF16(utf_cases[i].input16));
-      int input_len = static_cast<int>(input_str.length());
+      size_t input_len = input_str.length();
       bool success = true;
-      for (int ch = 0; ch < input_len; ch++) {
+      for (size_t ch = 0; ch < input_len; ch++) {
         success &= AppendUTF8EscapedChar(input_str.c_str(), &ch, input_len,
                                          &output);
       }
diff --git a/url/url_util.cc b/url/url_util.cc
index f56323e..a6d0901 100644
--- a/url/url_util.cc
+++ b/url/url_util.cc
@@ -811,11 +811,15 @@
                               int length,
                               DecodeURLMode mode,
                               CanonOutputW* output) {
+  if (length <= 0)
+    return;
+
   STACK_UNINITIALIZED RawCanonOutputT<char> unescaped_chars;
-  for (int i = 0; i < length; i++) {
+  size_t length_size_t = static_cast<size_t>(length);
+  for (size_t i = 0; i < length_size_t; i++) {
     if (input[i] == '%') {
       unsigned char ch;
-      if (DecodeEscaped(input, &i, length, &ch)) {
+      if (DecodeEscaped(input, &i, length_size_t, &ch)) {
         unescaped_chars.push_back(ch);
       } else {
         // Invalid escape sequence, copy the percent literal.
@@ -830,18 +834,20 @@
   int output_initial_length = output->length();
   // Convert that 8-bit to UTF-16. It's not clear IE does this at all to
   // JavaScript URLs, but Firefox and Safari do.
-  for (int i = 0; i < unescaped_chars.length(); i++) {
-    unsigned char uch = static_cast<unsigned char>(unescaped_chars.at(i));
+  size_t unescaped_length = static_cast<size_t>(unescaped_chars.length());
+  for (size_t i = 0; i < unescaped_length; i++) {
+    unsigned char uch =
+        static_cast<unsigned char>(unescaped_chars.at(static_cast<int>(i)));
     if (uch < 0x80) {
       // Non-UTF-8, just append directly
       output->push_back(uch);
     } else {
       // next_ch will point to the last character of the decoded
       // character.
-      int next_character = i;
+      size_t next_character = i;
       base_icu::UChar32 code_point;
-      if (ReadUTFChar(unescaped_chars.data(), &next_character,
-                      unescaped_chars.length(), &code_point)) {
+      if (ReadUTFChar(unescaped_chars.data(), &next_character, unescaped_length,
+                      &code_point)) {
         // Valid UTF-8 character, convert to UTF-16.
         AppendUTF16Value(code_point, output);
         i = next_character;