Commit bb739429b48 for php.net

commit bb739429b48130b0654fc460d4fee22e721b4cd8
Author: Tim Düsterhus <tim@tideways-gmbh.com>
Date:   Mon May 18 16:48:28 2026 +0200

    uri: Update to uriparser-1.0.2 (#22070)

    This fixes CVE-2026-44927 and CVE-2026-44928.

diff --git a/NEWS b/NEWS
index d0e3104f82d..7d4f5cde9fe 100644
--- a/NEWS
+++ b/NEWS
@@ -23,6 +23,14 @@ PHP                                                                        NEWS
   . Fixed bug GH-21689 (version_compare() incorrectly handles versions ending
     with a dot). (timwolla)

+- URI:
+  . Fixed CVE-2026-44927 (In uriparser before 1.0.2, there is pointer
+    difference truncation to int in various places). (CVE-2026-44927)
+    (Sebastian Pipping)
+  . Fixed CVE-2026-44928 (In uriparser before 1.0.2, the function family
+    EqualsUri can misclassify two unequal URIs as equal). (CVE-2026-44928)
+    (Sebastian Pipping)
+
 07 May 2026, PHP 8.5.6

 - Core:
diff --git a/ext/uri/uriparser/include/uriparser/Uri.h b/ext/uri/uriparser/include/uriparser/Uri.h
index f041f811353..ddbbd26f9e4 100644
--- a/ext/uri/uriparser/include/uriparser/Uri.h
+++ b/ext/uri/uriparser/include/uriparser/Uri.h
@@ -1,4 +1,4 @@
-/* 53c1cb9f2f728652fe001dc72fa0fa7a0e9fa0b8baaaa9e37561c6cdf88ac4df (1.0.1+)
+/* c9d94656d067288e474df19a062d487c736b0fa8517d2ef7bbeb8dcd5a70c05b (1.0.2+)
  *
  * uriparser - RFC 3986 URI parsing library
  *
diff --git a/ext/uri/uriparser/include/uriparser/UriBase.h b/ext/uri/uriparser/include/uriparser/UriBase.h
index abadcae0dbd..1cc91ceab77 100644
--- a/ext/uri/uriparser/include/uriparser/UriBase.h
+++ b/ext/uri/uriparser/include/uriparser/UriBase.h
@@ -52,7 +52,7 @@
 /* Version */
 #  define URI_VER_MAJOR 1
 #  define URI_VER_MINOR 0
-#  define URI_VER_RELEASE 1
+#  define URI_VER_RELEASE 2
 #  define URI_VER_SUFFIX_ANSI ""
 #  define URI_VER_SUFFIX_UNICODE URI_ANSI_TO_UNICODE(URI_VER_SUFFIX_ANSI)

diff --git a/ext/uri/uriparser/src/UriCommon.c b/ext/uri/uriparser/src/UriCommon.c
index 00256f201f7..e9a6992b01c 100644
--- a/ext/uri/uriparser/src/UriCommon.c
+++ b/ext/uri/uriparser/src/UriCommon.c
@@ -67,6 +67,7 @@

 #  include <assert.h>
 #  include <stddef.h>
+#  include <stdint.h>  // SIZE_MAX

 /*extern*/ const URI_CHAR * const URI_FUNC(SafeToPointTo) = _UT("X");
 /*extern*/ const URI_CHAR * const URI_FUNC(ConstPwd) = _UT(".");
@@ -105,46 +106,35 @@ int URI_FUNC(FreeUriPath)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) {
 }

 /* Compares two text ranges for equal text content */
-int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b) {
-    int diff;
-    ptrdiff_t lenA;
-    ptrdiff_t lenB;
-
+bool URI_FUNC(RangeEquals)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b) {
     /* NOTE: Both NULL means equal! */
     if ((a == NULL) || (b == NULL)) {
-        return ((a == NULL) ? 0 : 1) - ((b == NULL) ? 0 : 1);
+        return a == b;
     }

     /* NOTE: Both NULL means equal! */
     if ((a->first == NULL) || (b->first == NULL)) {
-        return ((a->first == NULL) ? 0 : 1) - ((b->first == NULL) ? 0 : 1);
-    }
-
-    lenA = a->afterLast - a->first;
-    lenB = b->afterLast - b->first;
-
-    if (lenA > lenB) {
-        return 1;
-    } else if (lenA < lenB) {
-        return -1;
+        return a->first == b->first;
     }

-    diff = URI_STRNCMP(a->first, b->first, (size_t)lenA);
+    const size_t lenA = a->afterLast - a->first;
+    const size_t lenB = b->afterLast - b->first;

-    if (diff > 0) {
-        return 1;
-    } else if (diff < 0) {
-        return -1;
+    if (lenA != lenB) {
+        return false;
     }

-    return diff;
+    return URI_STRNCMP(a->first, b->first, lenA) == 0;
 }

 UriBool URI_FUNC(CopyRange)(URI_TYPE(TextRange) * destRange,
                             const URI_TYPE(TextRange) * sourceRange,
                             UriMemoryManager * memory) {
-    const int lenInChars = (int)(sourceRange->afterLast - sourceRange->first);
-    const int lenInBytes = lenInChars * sizeof(URI_CHAR);
+    const size_t lenInChars = sourceRange->afterLast - sourceRange->first;
+    if (lenInChars > SIZE_MAX / sizeof(URI_CHAR)) {  // detect integer overflow
+        return URI_FALSE;
+    }
+    const size_t lenInBytes = lenInChars * sizeof(URI_CHAR);
     URI_CHAR * dup = memory->malloc(memory, lenInBytes);
     if (dup == NULL) {
         return URI_FALSE;
@@ -183,7 +173,7 @@ UriBool URI_FUNC(RemoveDotSegmentsEx)(URI_TYPE(Uri) * uri, UriBool relative,
     walker->reserved = NULL; /* Prev pointer */
     do {
         UriBool removeSegment = URI_FALSE;
-        int len = (int)(walker->text.afterLast - walker->text.first);
+        const size_t len = walker->text.afterLast - walker->text.first;
         switch (len) {
         case 1:
             if ((walker->text.first)[0] == _UT('.')) {
diff --git a/ext/uri/uriparser/src/UriCommon.h b/ext/uri/uriparser/src/UriCommon.h
index d141935f19e..12c691a7338 100644
--- a/ext/uri/uriparser/src/UriCommon.h
+++ b/ext/uri/uriparser/src/UriCommon.h
@@ -67,6 +67,8 @@
 #      include <uriparser/UriDefsUnicode.h>
 #    endif

+#    include <stdbool.h>
+
 /* Used to point to from empty path segments.
  * X.first and X.afterLast must be the same non-NULL value then. */
 extern const URI_CHAR * const URI_FUNC(SafeToPointTo);
@@ -77,7 +79,7 @@ void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri);

 int URI_FUNC(FreeUriPath)(URI_TYPE(Uri) * uri, UriMemoryManager * memory);

-int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b);
+bool URI_FUNC(RangeEquals)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b);

 UriBool URI_FUNC(CopyRange)(URI_TYPE(TextRange) * destRange,
                             const URI_TYPE(TextRange) * sourceRange,
diff --git a/ext/uri/uriparser/src/UriCompare.c b/ext/uri/uriparser/src/UriCompare.c
index 781100e7e6f..f9def86f666 100644
--- a/ext/uri/uriparser/src/UriCompare.c
+++ b/ext/uri/uriparser/src/UriCompare.c
@@ -72,17 +72,17 @@ UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a, const URI_TYPE(Uri) * b) {
     }

     /* scheme */
-    if (URI_FUNC(CompareRange)(&(a->scheme), &(b->scheme))) {
+    if (!URI_FUNC(RangeEquals)(&(a->scheme), &(b->scheme))) {
         return URI_FALSE;
     }

-    /* absolutePath */
-    if ((a->scheme.first == NULL) && (a->absolutePath != b->absolutePath)) {
+    /* absolutePath -- not meaningful for URIs with a host set! */
+    if (!URI_FUNC(HasHost)(a) && (a->absolutePath != b->absolutePath)) {
         return URI_FALSE;
     }

     /* userInfo */
-    if (URI_FUNC(CompareRange)(&(a->userInfo), &(b->userInfo))) {
+    if (!URI_FUNC(RangeEquals)(&(a->userInfo), &(b->userInfo))) {
         return URI_FALSE;
     }

@@ -107,20 +107,20 @@ UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a, const URI_TYPE(Uri) * b) {
     }

     if (a->hostData.ipFuture.first != NULL) {
-        if (URI_FUNC(CompareRange)(&(a->hostData.ipFuture), &(b->hostData.ipFuture))) {
+        if (!URI_FUNC(RangeEquals)(&(a->hostData.ipFuture), &(b->hostData.ipFuture))) {
             return URI_FALSE;
         }
     }

     if ((a->hostData.ip4 == NULL) && (a->hostData.ip6 == NULL)
         && (a->hostData.ipFuture.first == NULL)) {
-        if (URI_FUNC(CompareRange)(&(a->hostText), &(b->hostText))) {
+        if (!URI_FUNC(RangeEquals)(&(a->hostText), &(b->hostText))) {
             return URI_FALSE;
         }
     }

     /* portText */
-    if (URI_FUNC(CompareRange)(&(a->portText), &(b->portText))) {
+    if (!URI_FUNC(RangeEquals)(&(a->portText), &(b->portText))) {
         return URI_FALSE;
     }

@@ -133,7 +133,7 @@ UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a, const URI_TYPE(Uri) * b) {
         URI_TYPE(PathSegment) * walkA = a->pathHead;
         URI_TYPE(PathSegment) * walkB = b->pathHead;
         do {
-            if (URI_FUNC(CompareRange)(&(walkA->text), &(walkB->text))) {
+            if (!URI_FUNC(RangeEquals)(&(walkA->text), &(walkB->text))) {
                 return URI_FALSE;
             }
             if ((walkA->next == NULL) != (walkB->next == NULL)) {
@@ -145,12 +145,12 @@ UriBool URI_FUNC(EqualsUri)(const URI_TYPE(Uri) * a, const URI_TYPE(Uri) * b) {
     }

     /* query */
-    if (URI_FUNC(CompareRange)(&(a->query), &(b->query))) {
+    if (!URI_FUNC(RangeEquals)(&(a->query), &(b->query))) {
         return URI_FALSE;
     }

     /* fragment */
-    if (URI_FUNC(CompareRange)(&(a->fragment), &(b->fragment))) {
+    if (!URI_FUNC(RangeEquals)(&(a->fragment), &(b->fragment))) {
         return URI_FALSE;
     }

diff --git a/ext/uri/uriparser/src/UriCopy.c b/ext/uri/uriparser/src/UriCopy.c
index 3bc6b0dbe3f..fbe6340faa4 100644
--- a/ext/uri/uriparser/src/UriCopy.c
+++ b/ext/uri/uriparser/src/UriCopy.c
@@ -199,6 +199,12 @@ int URI_FUNC(CopyUriMm)(URI_TYPE(Uri) * destUri, const URI_TYPE(Uri) * sourceUri
             if (URI_FUNC(CopyRangeAsNeeded)(&destWalker->text, &sourceWalker->text,
                                             memory)
                 == URI_FALSE) {
+                // Unless wired to `destUri` above, `destWalker` may be hanging
+                // in the air now
+                if (destUri->pathHead != destWalker) {
+                    memory->free(memory, destWalker);
+                }
+
                 URI_FUNC(PreventLeakageAfterCopy)(destUri, revertMask, memory);
                 return URI_ERROR_MALLOC;
             }
diff --git a/ext/uri/uriparser/src/UriFile.c b/ext/uri/uriparser/src/UriFile.c
index 7510e701c9f..0af88480b0a 100644
--- a/ext/uri/uriparser/src/UriFile.c
+++ b/ext/uri/uriparser/src/UriFile.c
@@ -63,7 +63,8 @@
 #    include <uriparser/Uri.h>
 #  endif

-#  include <stdlib.h> /* for size_t, avoiding stddef.h for older MSVCs */
+#  include <stddef.h>  // size_t
+#  include <stdint.h>  // SIZE_MAX

 static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename,
                                                     URI_CHAR * uriString,
@@ -90,6 +91,11 @@ static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename,
                                                              : _UT("file:///");
         const size_t prefixLen = URI_STRLEN(prefix);

+        // Detect and avoid integer overflow
+        if (prefixLen > SIZE_MAX / sizeof(URI_CHAR)) {
+            return URI_ERROR_OUTPUT_TOO_LARGE;
+        }
+
         /* Copy prefix */
         memcpy(uriString, prefix, prefixLen * sizeof(URI_CHAR));
         output += prefixLen;
@@ -103,7 +109,13 @@ static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename,
             if (lastSep + 1 < input) {
                 if (!fromUnix && absolute && (firstSegment == URI_TRUE)) {
                     /* Quick hack to not convert "C:" to "C%3A" */
-                    const int charsToCopy = (int)(input - (lastSep + 1));
+                    const size_t charsToCopy = input - (lastSep + 1);
+
+                    // Detect and avoid integer overflow
+                    if (charsToCopy > SIZE_MAX / sizeof(URI_CHAR)) {
+                        return URI_ERROR_OUTPUT_TOO_LARGE;
+                    }
+
                     memcpy(output, lastSep + 1, charsToCopy * sizeof(URI_CHAR));
                     output += charsToCopy;
                 } else {
diff --git a/ext/uri/uriparser/src/UriNormalize.c b/ext/uri/uriparser/src/UriNormalize.c
index 8c812d37a0a..c73e22b2887 100644
--- a/ext/uri/uriparser/src/UriNormalize.c
+++ b/ext/uri/uriparser/src/UriNormalize.c
@@ -73,6 +73,7 @@
 #  endif

 #  include <assert.h>
+#  include <stdint.h>  // SIZE_MAX

 static int URI_FUNC(NormalizeSyntaxEngine)(URI_TYPE(Uri) * uri, unsigned int inMask,
                                            unsigned int * outMask,
@@ -254,20 +255,22 @@ URI_FUNC(LowercaseInplaceExceptPercentEncoding)(const URI_CHAR * first,
 static URI_INLINE UriBool URI_FUNC(LowercaseMalloc)(const URI_CHAR ** first,
                                                     const URI_CHAR ** afterLast,
                                                     UriMemoryManager * memory) {
-    int lenInChars;
     const int lowerUpperDiff = (_UT('a') - _UT('A'));
     URI_CHAR * buffer;
-    int i = 0;
+    size_t i = 0;

     if ((first == NULL) || (afterLast == NULL) || (*first == NULL)
         || (*afterLast == NULL)) {
         return URI_FALSE;
     }

-    lenInChars = (int)(*afterLast - *first);
+    const size_t lenInChars = *afterLast - *first;
     if (lenInChars == 0) {
         return URI_TRUE;
-    } else if (lenInChars < 0) {
+    }
+
+    // Detect and avoid integer overflow
+    if (lenInChars > SIZE_MAX / sizeof(URI_CHAR)) {
         return URI_FALSE;
     }

@@ -295,8 +298,8 @@ URI_FUNC(FixPercentEncodingEngine)(const URI_CHAR * inFirst, const URI_CHAR * in
                                    const URI_CHAR * outFirst,
                                    const URI_CHAR ** outAfterLast) {
     URI_CHAR * write = (URI_CHAR *)outFirst;
-    const int lenInChars = (int)(inAfterLast - inFirst);
-    int i = 0;
+    const size_t lenInChars = inAfterLast - inFirst;
+    size_t i = 0;

     /* All but last two */
     for (; i + 2 < lenInChars; i++) {
@@ -350,7 +353,6 @@ static URI_INLINE void URI_FUNC(FixPercentEncodingInplace)(const URI_CHAR * firs
 static URI_INLINE UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** first,
                                                              const URI_CHAR ** afterLast,
                                                              UriMemoryManager * memory) {
-    int lenInChars;
     URI_CHAR * buffer;

     /* Death checks */
@@ -360,10 +362,13 @@ static URI_INLINE UriBool URI_FUNC(FixPercentEncodingMalloc)(const URI_CHAR ** f
     }

     /* Old text length */
-    lenInChars = (int)(*afterLast - *first);
+    const size_t lenInChars = *afterLast - *first;
     if (lenInChars == 0) {
         return URI_TRUE;
-    } else if (lenInChars < 0) {
+    }
+
+    // Detect and avoid integer overflow
+    if (lenInChars > SIZE_MAX / sizeof(URI_CHAR)) {
         return URI_FALSE;
     }

diff --git a/ext/uri/uriparser/src/UriQuery.c b/ext/uri/uriparser/src/UriQuery.c
index 801a237a3a1..de3a040de04 100644
--- a/ext/uri/uriparser/src/UriQuery.c
+++ b/ext/uri/uriparser/src/UriQuery.c
@@ -67,6 +67,7 @@

 #  include <limits.h>
 #  include <stddef.h> /* size_t */
+#  include <stdint.h>  // SIZE_MAX

 static int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest,
                                         const URI_TYPE(QueryList) * queryList,
@@ -254,7 +255,14 @@ int URI_FUNC(ComposeQueryEngine)(URI_CHAR * dest, const URI_TYPE(QueryList) * qu
     if (dest != NULL) {
         write[0] = _UT('\0');
         if (charsWritten != NULL) {
-            *charsWritten = (int)(write - dest) + 1; /* .. for terminator */
+            const size_t lenInChars = write - dest;
+
+            // Detect and avoid integer overflow
+            if (lenInChars > INT_MAX - 1) {
+                return URI_ERROR_OUTPUT_TOO_LARGE;
+            }
+
+            *charsWritten = (int)(lenInChars + 1); /* .. for terminator */
         }
     }

@@ -267,8 +275,8 @@ UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) * *prevNext, int * itemCou
                                   const URI_CHAR * valueAfter, UriBool plusToSpace,
                                   UriBreakConversion breakConversion,
                                   UriMemoryManager * memory) {
-    const int keyLen = (int)(keyAfter - keyFirst);
-    const int valueLen = (int)(valueAfter - valueFirst);
+    const size_t keyLen = keyAfter - keyFirst;
+    const size_t valueLen = valueAfter - valueFirst;
     URI_CHAR * key;
     URI_CHAR * value;

@@ -285,6 +293,13 @@ UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) * *prevNext, int * itemCou
     }
     (*prevNext)->next = NULL;

+    // Detect integer overflow
+    if ((keyLen > SIZE_MAX - 1) || (keyLen + 1 > SIZE_MAX / sizeof(URI_CHAR))) {
+        memory->free(memory, *prevNext);
+        *prevNext = NULL;
+        return URI_FALSE;  // Raises malloc error
+    }
+
     /* Fill key */
     key = memory->malloc(memory, (keyLen + 1) * sizeof(URI_CHAR));
     if (key == NULL) {
@@ -305,6 +320,14 @@ UriBool URI_FUNC(AppendQueryItem)(URI_TYPE(QueryList) * *prevNext, int * itemCou

     /* Fill value */
     if (valueFirst != NULL) {
+        // Detect integer overflow
+        if ((valueLen > SIZE_MAX - 1) || (valueLen + 1 > SIZE_MAX / sizeof(URI_CHAR))) {
+            memory->free(memory, key);
+            memory->free(memory, *prevNext);
+            *prevNext = NULL;
+            return URI_FALSE;  // Raises malloc error
+        }
+
         value = memory->malloc(memory, (valueLen + 1) * sizeof(URI_CHAR));
         if (value == NULL) {
             memory->free(memory, key);
diff --git a/ext/uri/uriparser/src/UriRecompose.c b/ext/uri/uriparser/src/UriRecompose.c
index 61ffee77248..055e0483d3f 100644
--- a/ext/uri/uriparser/src/UriRecompose.c
+++ b/ext/uri/uriparser/src/UriRecompose.c
@@ -64,6 +64,9 @@
 #    include "UriCommon.h"
 #  endif

+#  include <limits.h>  // INT_MAX
+#  include <stdint.h>  // SIZE_MAX
+
 static int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(Uri) * uri,
                                     int maxChars, int * charsWritten,
                                     int * charsRequired);
@@ -116,10 +119,19 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                     /* clang-format off */
     /* [03/19]     append scheme to result; */
                     /* clang-format on */
-                    const int charsToWrite =
-                        (int)(uri->scheme.afterLast - uri->scheme.first);
+                    const size_t charsToWrite = uri->scheme.afterLast - uri->scheme.first;
                     if (dest != NULL) {
-                        if (written + charsToWrite <= maxChars) {
+                        // Detect and avoid integer overflow
+                        if (charsToWrite > (size_t)INT_MAX - written) {
+                            return URI_ERROR_TOSTRING_TOO_LONG;
+                        }
+
+                        if (written + charsToWrite <= (size_t)maxChars) {
+                            // Detect and avoid integer overflow
+                            if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
                             memcpy(dest + written, uri->scheme.first,
                                    charsToWrite * sizeof(URI_CHAR));
                             written += charsToWrite;
@@ -131,6 +143,11 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                             return URI_ERROR_TOSTRING_TOO_LONG;
                         }
                     } else {
+                        // Detect and avoid integer overflow
+                        if (charsToWrite > (size_t)INT_MAX - *charsRequired) {
+                            return URI_ERROR_TOSTRING_TOO_LONG;
+                        }
+
                         (*charsRequired) += charsToWrite;
                     }
                     /* clang-format off */
@@ -180,10 +197,20 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                     /* clang-format on */
                     /* UserInfo */
                     if (uri->userInfo.first != NULL) {
-                        const int charsToWrite =
-                            (int)(uri->userInfo.afterLast - uri->userInfo.first);
+                        const size_t charsToWrite =
+                            uri->userInfo.afterLast - uri->userInfo.first;
                         if (dest != NULL) {
-                            if (written + charsToWrite <= maxChars) {
+                            // Detect and avoid integer overflow
+                            if (charsToWrite > (size_t)INT_MAX - written) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
+                            if (written + charsToWrite <= (size_t)maxChars) {
+                                // Detect and avoid integer overflow
+                                if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) {
+                                    return URI_ERROR_TOSTRING_TOO_LONG;
+                                }
+
                                 memcpy(dest + written, uri->userInfo.first,
                                        charsToWrite * sizeof(URI_CHAR));
                                 written += charsToWrite;
@@ -206,6 +233,13 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                                 return URI_ERROR_TOSTRING_TOO_LONG;
                             }
                         } else {
+                            // Detect and avoid integer overflow
+                            if ((charsToWrite > (size_t)INT_MAX - 1)
+                                || (charsToWrite + 1
+                                    > (size_t)INT_MAX - *charsRequired)) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
                             (*charsRequired) += charsToWrite + 1;
                         }
                     }
@@ -334,8 +368,8 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                         }
                     } else if (uri->hostData.ipFuture.first != NULL) {
                         /* IPvFuture */
-                        const int charsToWrite = (int)(uri->hostData.ipFuture.afterLast
-                                                       - uri->hostData.ipFuture.first);
+                        const size_t charsToWrite = uri->hostData.ipFuture.afterLast
+                                                    - uri->hostData.ipFuture.first;
                         if (dest != NULL) {
                             if (written + 1 <= maxChars) {
                                 memcpy(dest + written, _UT("["), 1 * sizeof(URI_CHAR));
@@ -348,7 +382,17 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                                 return URI_ERROR_TOSTRING_TOO_LONG;
                             }

-                            if (written + charsToWrite <= maxChars) {
+                            // Detect and avoid integer overflow
+                            if (charsToWrite > (size_t)INT_MAX - written) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
+                            if (written + charsToWrite <= (size_t)maxChars) {
+                                // Detect and avoid integer overflow
+                                if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) {
+                                    return URI_ERROR_TOSTRING_TOO_LONG;
+                                }
+
                                 memcpy(dest + written, uri->hostData.ipFuture.first,
                                        charsToWrite * sizeof(URI_CHAR));
                                 written += charsToWrite;
@@ -371,14 +415,31 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                                 return URI_ERROR_TOSTRING_TOO_LONG;
                             }
                         } else {
+                            // Detect and avoid integer overflow
+                            if ((charsToWrite > (size_t)INT_MAX - 1 - 1)
+                                || (1 + charsToWrite + 1
+                                    > (size_t)INT_MAX - *charsRequired)) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
                             (*charsRequired) += 1 + charsToWrite + 1;
                         }
                     } else if (uri->hostText.first != NULL) {
                         /* Regname */
-                        const int charsToWrite =
-                            (int)(uri->hostText.afterLast - uri->hostText.first);
+                        const size_t charsToWrite =
+                            uri->hostText.afterLast - uri->hostText.first;
                         if (dest != NULL) {
-                            if (written + charsToWrite <= maxChars) {
+                            // Detect and avoid integer overflow
+                            if (charsToWrite > (size_t)INT_MAX - written) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
+                            if (written + charsToWrite <= (size_t)maxChars) {
+                                // Detect and avoid integer overflow
+                                if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) {
+                                    return URI_ERROR_TOSTRING_TOO_LONG;
+                                }
+
                                 memcpy(dest + written, uri->hostText.first,
                                        charsToWrite * sizeof(URI_CHAR));
                                 written += charsToWrite;
@@ -390,14 +451,19 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                                 return URI_ERROR_TOSTRING_TOO_LONG;
                             }
                         } else {
+                            // Detect and avoid integer overflow
+                            if (charsToWrite > (size_t)INT_MAX - *charsRequired) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
                             (*charsRequired) += charsToWrite;
                         }
                     }

                     /* Port */
                     if (uri->portText.first != NULL) {
-                        const int charsToWrite =
-                            (int)(uri->portText.afterLast - uri->portText.first);
+                        const size_t charsToWrite =
+                            uri->portText.afterLast - uri->portText.first;
                         if (dest != NULL) {
                             /* Leading ':' */
                             if (written + 1 <= maxChars) {
@@ -411,8 +477,18 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                                 return URI_ERROR_TOSTRING_TOO_LONG;
                             }

+                            // Detect and avoid integer overflow
+                            if (charsToWrite > (size_t)INT_MAX - written) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
                             /* Port number */
-                            if (written + charsToWrite <= maxChars) {
+                            if (written + charsToWrite <= (size_t)maxChars) {
+                                // Detect and avoid integer overflow
+                                if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) {
+                                    return URI_ERROR_TOSTRING_TOO_LONG;
+                                }
+
                                 memcpy(dest + written, uri->portText.first,
                                        charsToWrite * sizeof(URI_CHAR));
                                 written += charsToWrite;
@@ -424,6 +500,13 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                                 return URI_ERROR_TOSTRING_TOO_LONG;
                             }
                         } else {
+                            // Detect and avoid integer overflow
+                            if ((charsToWrite > (size_t)INT_MAX - 1)
+                                || (1 + charsToWrite
+                                    > (size_t)INT_MAX - *charsRequired)) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
                             (*charsRequired) += 1 + charsToWrite;
                         }
                     }
@@ -456,10 +539,20 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                 if (uri->pathHead != NULL) {
                     URI_TYPE(PathSegment) * walker = uri->pathHead;
                     do {
-                        const int charsToWrite =
-                            (int)(walker->text.afterLast - walker->text.first);
+                        const size_t charsToWrite =
+                            walker->text.afterLast - walker->text.first;
                         if (dest != NULL) {
-                            if (written + charsToWrite <= maxChars) {
+                            // Detect and avoid integer overflow
+                            if (charsToWrite > (size_t)INT_MAX - written) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
+                            if (written + charsToWrite <= (size_t)maxChars) {
+                                // Detect and avoid integer overflow
+                                if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) {
+                                    return URI_ERROR_TOSTRING_TOO_LONG;
+                                }
+
                                 memcpy(dest + written, walker->text.first,
                                        charsToWrite * sizeof(URI_CHAR));
                                 written += charsToWrite;
@@ -471,6 +564,11 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                                 return URI_ERROR_TOSTRING_TOO_LONG;
                             }
                         } else {
+                            // Detect and avoid integer overflow
+                            if (charsToWrite > (size_t)INT_MAX - *charsRequired) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
                             (*charsRequired) += charsToWrite;
                         }

@@ -520,10 +618,19 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                     /* clang-format off */
     /* [13/19]     append query to result; */
                     /* clang-format on */
-                    const int charsToWrite =
-                        (int)(uri->query.afterLast - uri->query.first);
+                    const size_t charsToWrite = uri->query.afterLast - uri->query.first;
                     if (dest != NULL) {
-                        if (written + charsToWrite <= maxChars) {
+                        // Detect and avoid integer overflow
+                        if (charsToWrite > (size_t)INT_MAX - written) {
+                            return URI_ERROR_TOSTRING_TOO_LONG;
+                        }
+
+                        if (written + charsToWrite <= (size_t)maxChars) {
+                            // Detect and avoid integer overflow
+                            if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
                             memcpy(dest + written, uri->query.first,
                                    charsToWrite * sizeof(URI_CHAR));
                             written += charsToWrite;
@@ -535,6 +642,11 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                             return URI_ERROR_TOSTRING_TOO_LONG;
                         }
                     } else {
+                        // Detect and avoid integer overflow
+                        if (charsToWrite > (size_t)INT_MAX - *charsRequired) {
+                            return URI_ERROR_TOSTRING_TOO_LONG;
+                        }
+
                         (*charsRequired) += charsToWrite;
                     }
                     /* clang-format off */
@@ -565,10 +677,20 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                     /* clang-format off */
     /* [17/19]     append fragment to result; */
                     /* clang-format on */
-                    const int charsToWrite =
-                        (int)(uri->fragment.afterLast - uri->fragment.first);
+                    const size_t charsToWrite =
+                        uri->fragment.afterLast - uri->fragment.first;
                     if (dest != NULL) {
-                        if (written + charsToWrite <= maxChars) {
+                        // Detect and avoid integer overflow
+                        if (charsToWrite > (size_t)INT_MAX - written) {
+                            return URI_ERROR_TOSTRING_TOO_LONG;
+                        }
+
+                        if (written + charsToWrite <= (size_t)maxChars) {
+                            // Detect and avoid integer overflow
+                            if (charsToWrite > SIZE_MAX / sizeof(URI_CHAR)) {
+                                return URI_ERROR_TOSTRING_TOO_LONG;
+                            }
+
                             memcpy(dest + written, uri->fragment.first,
                                    charsToWrite * sizeof(URI_CHAR));
                             written += charsToWrite;
@@ -580,6 +702,11 @@ static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(U
                             return URI_ERROR_TOSTRING_TOO_LONG;
                         }
                     } else {
+                        // Detect and avoid integer overflow
+                        if (charsToWrite > (size_t)INT_MAX - *charsRequired) {
+                            return URI_ERROR_TOSTRING_TOO_LONG;
+                        }
+
                         (*charsRequired) += charsToWrite;
                     }
                     /* clang-format off */
diff --git a/ext/uri/uriparser/src/UriResolve.c b/ext/uri/uriparser/src/UriResolve.c
index 302665d21cd..90c8bfd778d 100644
--- a/ext/uri/uriparser/src/UriResolve.c
+++ b/ext/uri/uriparser/src/UriResolve.c
@@ -183,9 +183,8 @@ static int URI_FUNC(AddBaseUriImpl)(URI_TYPE(Uri) * absDest,
                 if ((options & URI_RESOLVE_IDENTICAL_SCHEME_COMPAT)
                     && (absBase->scheme.first != NULL)
                     && (relSource->scheme.first != NULL)
-                    && (0
-                        == URI_FUNC(CompareRange)(&(absBase->scheme),
-                                                  &(relSource->scheme)))) {
+                    && (URI_FUNC(RangeEquals)(&(absBase->scheme),
+                                              &(relSource->scheme)))) {
                     /* clang-format off */
     /* [00/32]     undefine(R.scheme); */
                     /* clang-format on */
diff --git a/ext/uri/uriparser/src/UriShorten.c b/ext/uri/uriparser/src/UriShorten.c
index 548b0b4157d..001bd7db999 100644
--- a/ext/uri/uriparser/src/UriShorten.c
+++ b/ext/uri/uriparser/src/UriShorten.c
@@ -111,14 +111,14 @@ static URI_INLINE UriBool URI_FUNC(EqualsAuthority)(const URI_TYPE(Uri) * first,
     /* IPvFuture */
     if (first->hostData.ipFuture.first != NULL) {
         return ((second->hostData.ipFuture.first != NULL)
-                && !URI_FUNC(CompareRange)(&first->hostData.ipFuture,
-                                           &second->hostData.ipFuture))
+                && URI_FUNC(RangeEquals)(&first->hostData.ipFuture,
+                                         &second->hostData.ipFuture))
                    ? URI_TRUE
                    : URI_FALSE;
     }

-    return !URI_FUNC(CompareRange)(&first->hostText, &second->hostText) ? URI_TRUE
-                                                                        : URI_FALSE;
+    return URI_FUNC(RangeEquals)(&first->hostText, &second->hostText) ? URI_TRUE
+                                                                      : URI_FALSE;
 }

 static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest,
@@ -152,7 +152,7 @@ static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest,
                 /* clang-format off */
     /* [01/50] if (A.scheme != Base.scheme) then */
                 /* clang-format on */
-                if (URI_FUNC(CompareRange)(&absSource->scheme, &absBase->scheme)) {
+                if (!URI_FUNC(RangeEquals)(&absSource->scheme, &absBase->scheme)) {
                     /* clang-format off */
     /* [02/50]    T.scheme    = A.scheme; */
                     /* clang-format on */
@@ -255,8 +255,7 @@ static int URI_FUNC(RemoveBaseUriImpl)(URI_TYPE(Uri) * dest,
                             /* clang-format on */
                             while (
                                 (sourceSeg != NULL) && (baseSeg != NULL)
-                                && !URI_FUNC(CompareRange)(&sourceSeg->text,
-                                                           &baseSeg->text)
+                                && URI_FUNC(RangeEquals)(&sourceSeg->text, &baseSeg->text)
                                 && !((sourceSeg->text.first == sourceSeg->text.afterLast)
                                      && ((sourceSeg->next == NULL)
                                          != (baseSeg->next == NULL)))) {