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)))) {