From 671f95eea3de8711c66f2394b1e56bc6b3e33043 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 2 Dec 2025 19:04:36 +0000 Subject: [PATCH 01/12] Fix GH-20603 issue on windows 32 bits. the timeout needed to be unsigned. close GH-20634 --- ext/ftp/php_ftp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index 5a7cfe18dac82..f19cc4b4b6b71 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -147,7 +147,7 @@ PHP_FUNCTION(ftp_connect) RETURN_THROWS(); } - const zend_long timeoutmax = (zend_long)((double) PHP_TIMEOUT_ULL_MAX / 1000000.0); + const uint64_t timeoutmax = (uint64_t)((double) PHP_TIMEOUT_ULL_MAX / 1000000.0); if (timeout_sec <= 0) { zend_argument_value_error(3, "must be greater than 0"); @@ -155,7 +155,7 @@ PHP_FUNCTION(ftp_connect) } if (timeout_sec >= timeoutmax) { - zend_argument_value_error(3, "must be less than " ZEND_LONG_FMT, timeoutmax); + zend_argument_value_error(3, "must be less than " ZEND_ULONG_FMT, timeoutmax); RETURN_THROWS(); } From 3ae61e46668d9e58bc859369769b285035a55174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 9 Dec 2025 11:52:42 +0100 Subject: [PATCH 02/12] uri: Update to uriparser-0.9.9-79-gf47a7f0 (#20671) This is in preparation of importing a fix for the uriparser/uriparser#282 security issue, which will likely depend on this refactoring to cleanly apply. --- ext/uri/uriparser/src/UriCommon.c | 28 +- ext/uri/uriparser/src/UriEscape.c | 114 +----- ext/uri/uriparser/src/UriIp4.c | 23 +- ext/uri/uriparser/src/UriParse.c | 412 +++------------------- ext/uri/uriparser/src/UriSetFragment.c | 107 +----- ext/uri/uriparser/src/UriSetHostRegName.c | 103 +----- ext/uri/uriparser/src/UriSetPath.c | 107 +----- ext/uri/uriparser/src/UriSetPort.c | 14 +- ext/uri/uriparser/src/UriSetQuery.c | 107 +----- ext/uri/uriparser/src/UriSetScheme.c | 81 +---- ext/uri/uriparser/src/UriSetUserInfo.c | 103 +----- ext/uri/uriparser/src/UriSets.h | 174 +++++++++ 12 files changed, 253 insertions(+), 1120 deletions(-) create mode 100644 ext/uri/uriparser/src/UriSets.h diff --git a/ext/uri/uriparser/src/UriCommon.c b/ext/uri/uriparser/src/UriCommon.c index a594fcceed716..3644e8828f35f 100644 --- a/ext/uri/uriparser/src/UriCommon.c +++ b/ext/uri/uriparser/src/UriCommon.c @@ -62,6 +62,7 @@ # ifndef URI_DOXYGEN # include # include "UriCommon.h" +# include "UriSets.h" # endif # include @@ -468,32 +469,11 @@ UriBool URI_FUNC(RemoveDotSegmentsAbsolute)(URI_TYPE(Uri) * uri, unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig) { switch (hexdig) { - case _UT('0'): - case _UT('1'): - case _UT('2'): - case _UT('3'): - case _UT('4'): - case _UT('5'): - case _UT('6'): - case _UT('7'): - case _UT('8'): - case _UT('9'): + case URI_SET_DIGIT(_UT): return (unsigned char)(9 + hexdig - _UT('9')); - - case _UT('a'): - case _UT('b'): - case _UT('c'): - case _UT('d'): - case _UT('e'): - case _UT('f'): + case URI_SET_HEX_LETTER_LOWER(_UT): return (unsigned char)(15 + hexdig - _UT('f')); - - case _UT('A'): - case _UT('B'): - case _UT('C'): - case _UT('D'): - case _UT('E'): - case _UT('F'): + case URI_SET_HEX_LETTER_UPPER(_UT): return (unsigned char)(15 + hexdig - _UT('F')); default: diff --git a/ext/uri/uriparser/src/UriEscape.c b/ext/uri/uriparser/src/UriEscape.c index b23050783fb33..a1763f97153cf 100644 --- a/ext/uri/uriparser/src/UriEscape.c +++ b/ext/uri/uriparser/src/UriEscape.c @@ -62,6 +62,7 @@ # ifndef URI_DOXYGEN # include # include "UriCommon.h" +# include "UriSets.h" # endif URI_CHAR * URI_FUNC(Escape)(const URI_CHAR * in, URI_CHAR * out, UriBool spaceToPlus, @@ -108,72 +109,7 @@ URI_CHAR * URI_FUNC(EscapeEx)(const URI_CHAR * inFirst, const URI_CHAR * inAfter prevWasCr = URI_FALSE; break; - case _UT('a'): /* ALPHA */ - case _UT('A'): - case _UT('b'): - case _UT('B'): - case _UT('c'): - case _UT('C'): - case _UT('d'): - case _UT('D'): - case _UT('e'): - case _UT('E'): - case _UT('f'): - case _UT('F'): - case _UT('g'): - case _UT('G'): - case _UT('h'): - case _UT('H'): - case _UT('i'): - case _UT('I'): - case _UT('j'): - case _UT('J'): - case _UT('k'): - case _UT('K'): - case _UT('l'): - case _UT('L'): - case _UT('m'): - case _UT('M'): - case _UT('n'): - case _UT('N'): - case _UT('o'): - case _UT('O'): - case _UT('p'): - case _UT('P'): - case _UT('q'): - case _UT('Q'): - case _UT('r'): - case _UT('R'): - case _UT('s'): - case _UT('S'): - case _UT('t'): - case _UT('T'): - case _UT('u'): - case _UT('U'): - case _UT('v'): - case _UT('V'): - case _UT('w'): - case _UT('W'): - case _UT('x'): - case _UT('X'): - case _UT('y'): - case _UT('Y'): - case _UT('z'): - case _UT('Z'): - case _UT('0'): /* DIGIT */ - case _UT('1'): - case _UT('2'): - case _UT('3'): - case _UT('4'): - case _UT('5'): - case _UT('6'): - case _UT('7'): - case _UT('8'): - case _UT('9'): - case _UT('-'): /* "-" / "." / "_" / "~" */ - case _UT('.'): - case _UT('_'): - case _UT('~'): + case URI_SET_UNRESERVED(_UT): /* Copy unmodified */ write[0] = read[0]; write++; @@ -263,51 +199,9 @@ const URI_CHAR * URI_FUNC(UnescapeInPlaceEx)(URI_CHAR * inout, UriBool plusToSpa case _UT('%'): switch (read[1]) { - case _UT('0'): - case _UT('1'): - case _UT('2'): - case _UT('3'): - case _UT('4'): - case _UT('5'): - case _UT('6'): - case _UT('7'): - case _UT('8'): - case _UT('9'): - case _UT('a'): - case _UT('b'): - case _UT('c'): - case _UT('d'): - case _UT('e'): - case _UT('f'): - case _UT('A'): - case _UT('B'): - case _UT('C'): - case _UT('D'): - case _UT('E'): - case _UT('F'): + case URI_SET_HEXDIG(_UT): switch (read[2]) { - case _UT('0'): - case _UT('1'): - case _UT('2'): - case _UT('3'): - case _UT('4'): - case _UT('5'): - case _UT('6'): - case _UT('7'): - case _UT('8'): - case _UT('9'): - case _UT('a'): - case _UT('b'): - case _UT('c'): - case _UT('d'): - case _UT('e'): - case _UT('f'): - case _UT('A'): - case _UT('B'): - case _UT('C'): - case _UT('D'): - case _UT('E'): - case _UT('F'): { + case URI_SET_HEXDIG(_UT): { /* Percent group found */ const unsigned char left = URI_FUNC(HexdigToInt)(read[1]); const unsigned char right = URI_FUNC(HexdigToInt)(read[2]); diff --git a/ext/uri/uriparser/src/UriIp4.c b/ext/uri/uriparser/src/UriIp4.c index 162a75a556d49..ae61141f7a3ad 100644 --- a/ext/uri/uriparser/src/UriIp4.c +++ b/ext/uri/uriparser/src/UriIp4.c @@ -68,6 +68,7 @@ # include # include "UriIp4Base.h" # include +# include "UriSets.h" # endif /* Prototypes */ @@ -194,16 +195,7 @@ URI_FUNC(ParseDecOctetOne)(UriIp4Parser * parser, const URI_CHAR * first, } switch (*first) { - case _UT('0'): - case _UT('1'): - case _UT('2'): - case _UT('3'): - case _UT('4'): - case _UT('5'): - case _UT('6'): - case _UT('7'): - case _UT('8'): - case _UT('9'): + case URI_SET_DIGIT(_UT): uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); return (const URI_CHAR *)URI_FUNC(ParseDecOctetThree)(parser, first + 1, afterLast); @@ -272,16 +264,7 @@ URI_FUNC(ParseDecOctetThree)(UriIp4Parser * parser, const URI_CHAR * first, } switch (*first) { - case _UT('0'): - case _UT('1'): - case _UT('2'): - case _UT('3'): - case _UT('4'): - case _UT('5'): - case _UT('6'): - case _UT('7'): - case _UT('8'): - case _UT('9'): + case URI_SET_DIGIT(_UT): uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); return first + 1; diff --git a/ext/uri/uriparser/src/UriParse.c b/ext/uri/uriparser/src/UriParse.c index db48b380464b1..ed851e94fbd9c 100644 --- a/ext/uri/uriparser/src/UriParse.c +++ b/ext/uri/uriparser/src/UriParse.c @@ -71,82 +71,9 @@ # include "UriCommon.h" # include "UriMemory.h" # include "UriParseBase.h" +# include "UriSets.h" # endif -# define URI_SET_DIGIT \ - _UT('0') : case _UT('1'): \ - case _UT('2'): \ - case _UT('3'): \ - case _UT('4'): \ - case _UT('5'): \ - case _UT('6'): \ - case _UT('7'): \ - case _UT('8'): \ - case _UT('9') - -# define URI_SET_HEX_LETTER_UPPER \ - _UT('A') : case _UT('B'): \ - case _UT('C'): \ - case _UT('D'): \ - case _UT('E'): \ - case _UT('F') - -# define URI_SET_HEX_LETTER_LOWER \ - _UT('a') : case _UT('b'): \ - case _UT('c'): \ - case _UT('d'): \ - case _UT('e'): \ - case _UT('f') - -# define URI_SET_HEXDIG \ - URI_SET_DIGIT: \ - case URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER - -# define URI_SET_ALPHA \ - URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER: \ - case _UT('g'): \ - case _UT('G'): \ - case _UT('h'): \ - case _UT('H'): \ - case _UT('i'): \ - case _UT('I'): \ - case _UT('j'): \ - case _UT('J'): \ - case _UT('k'): \ - case _UT('K'): \ - case _UT('l'): \ - case _UT('L'): \ - case _UT('m'): \ - case _UT('M'): \ - case _UT('n'): \ - case _UT('N'): \ - case _UT('o'): \ - case _UT('O'): \ - case _UT('p'): \ - case _UT('P'): \ - case _UT('q'): \ - case _UT('Q'): \ - case _UT('r'): \ - case _UT('R'): \ - case _UT('s'): \ - case _UT('S'): \ - case _UT('t'): \ - case _UT('T'): \ - case _UT('u'): \ - case _UT('U'): \ - case _UT('v'): \ - case _UT('V'): \ - case _UT('w'): \ - case _UT('W'): \ - case _UT('x'): \ - case _UT('X'): \ - case _UT('y'): \ - case _UT('Y'): \ - case _UT('z'): \ - case _UT('Z') - static const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, @@ -340,26 +267,7 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState return URI_FUNC(ParseAuthorityTwo)(state, afterIpLit2, afterLast); } - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: + case URI_SET_PCHAR(_UT): state->uri->userInfo.first = first; /* USERINFO BEGIN */ return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast, memory); @@ -411,7 +319,7 @@ static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, } switch (*first) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): return URI_FUNC(ParseHexZero)(state, first + 1, afterLast); default: @@ -433,26 +341,7 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) } switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: + case URI_SET_PCHAR(_UT): return URI_FUNC(ParsePathRootless)(state, first, afterLast, memory); case _UT('/'): @@ -478,24 +367,9 @@ static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, } switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): case _UT(':'): - case _UT(';'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): return URI_FUNC(ParseIpFutStopGo)(state, first + 1, afterLast, memory); default: @@ -517,24 +391,9 @@ static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state } switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): case _UT(':'): - case _UT(';'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): return URI_FUNC(ParseIpFutLoop)(state, first, afterLast, memory); default: @@ -568,7 +427,7 @@ static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, } switch (first[1]) { - case URI_SET_HEXDIG: { + case URI_SET_HEXDIG(_UT): { const URI_CHAR * afterIpFutLoop; const URI_CHAR * const afterHexZero = URI_FUNC(ParseHexZero)(state, first + 2, afterLast); @@ -643,7 +502,7 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * case _UT(':'): case _UT(']'): - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): state->uri->hostData.ip6 = memory->malloc( memory, 1 * sizeof(UriIp6)); /* Freed when stopping on parse error */ if (state->uri->hostData.ip6 == NULL) { @@ -685,7 +544,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat /* Eat rest of IPv4 address */ for (;;) { switch (*first) { - case URI_SET_DIGIT: + case URI_SET_DIGIT(_UT): if (digitCount == 4) { URI_FUNC(StopSyntax)(state, first, memory); return NULL; @@ -780,7 +639,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat int walking = 1; do { switch (*first) { - case URI_SET_HEX_LETTER_LOWER: + case URI_SET_HEX_LETTER_LOWER(_UT): letterAmong = 1; if (digitCount == 4) { URI_FUNC(StopSyntax)(state, first, memory); @@ -790,7 +649,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat digitCount++; break; - case URI_SET_HEX_LETTER_UPPER: + case URI_SET_HEX_LETTER_UPPER(_UT): letterAmong = 1; if (digitCount == 4) { URI_FUNC(StopSyntax)(state, first, memory); @@ -800,7 +659,7 @@ static const URI_CHAR * URI_FUNC(ParseIPv6address2)(URI_TYPE(ParserState) * stat digitCount++; break; - case URI_SET_DIGIT: + case URI_SET_DIGIT(_UT): if (digitCount == 4) { URI_FUNC(StopSyntax)(state, first, memory); return NULL; @@ -995,23 +854,8 @@ static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * } case _UT('@'): - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('*'): - case _UT(','): - case _UT(';'): - case _UT('\''): - case _UT('+'): - case _UT('='): - case _UT('-'): - case _UT('.'): - case _UT('_'): - case _UT('~'): - case URI_SET_DIGIT: - case URI_SET_ALPHA: + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast, memory); case _UT('/'): { @@ -1118,24 +962,9 @@ static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, } switch (*first) { - case _UT('!'): - case _UT('$'): case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(';'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: { + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): { const URI_CHAR * const afterPctSubUnres = URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory); if (afterPctSubUnres == NULL) { @@ -1193,26 +1022,7 @@ URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * f } switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: + case URI_SET_PCHAR(_UT): return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast, memory); default: @@ -1239,24 +1049,9 @@ static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * } switch (*first) { - case _UT('!'): - case _UT('$'): case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(';'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: { + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): { const URI_CHAR * const afterPctSubUnres = URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory); if (afterPctSubUnres == NULL) { @@ -1331,19 +1126,7 @@ static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * s } switch (*first) { - /* begin sub-delims */ - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('\''): - case _UT('('): - case _UT(')'): - case _UT('*'): - case _UT('+'): - case _UT(','): - case _UT(';'): - case _UT('='): - /* end sub-delims */ + case URI_SET_SUB_DELIMS(_UT): /* begin unreserved (except alpha and digit) */ case _UT('-'): case _UT('.'): @@ -1351,12 +1134,12 @@ static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * s case _UT('~'): /* end unreserved (except alpha and digit) */ case _UT(':'): - case URI_SET_ALPHA: + case URI_SET_ALPHA(_UT): state->uri->hostText.afterLast = NULL; /* Not a host, reset */ state->uri->portText.first = NULL; /* Not a port, reset */ return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast, memory); - case URI_SET_DIGIT: + case URI_SET_DIGIT(_UT): return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast, memory); case _UT('%'): @@ -1399,24 +1182,9 @@ static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state } switch (*first) { - case _UT('!'): - case _UT('$'): case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(';'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: { + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): { const URI_CHAR * const afterPctSubUnres = URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory); if (afterPctSubUnres == NULL) { @@ -1522,26 +1290,7 @@ URI_FUNC(ParsePathAbsNoLeadSlash)(URI_TYPE(ParserState) * state, const URI_CHAR } switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: { + case URI_SET_PCHAR(_UT): { const URI_CHAR * const afterSegmentNz = URI_FUNC(ParseSegmentNz)(state, first, afterLast, memory); if (afterSegmentNz == NULL) { @@ -1600,25 +1349,7 @@ static const URI_CHAR * URI_FUNC(ParsePchar)(URI_TYPE(ParserState) * state, case _UT('%'): return URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); - case _UT(':'): - case _UT('@'): - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('*'): - case _UT(','): - case _UT(';'): - case _UT('\''): - case _UT('+'): - case _UT('='): - case _UT('-'): - case _UT('.'): - case _UT('_'): - case _UT('~'): - case URI_SET_DIGIT: - case URI_SET_ALPHA: + case URI_SET_PCHAR_WITHOUT_PERCENT(_UT): return first + 1; default: @@ -1652,14 +1383,14 @@ static const URI_CHAR * URI_FUNC(ParsePctEncoded)(URI_TYPE(ParserState) * state, } switch (first[1]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): if (afterLast - first < 3) { URI_FUNC(StopSyntax)(state, afterLast, memory); return NULL; } switch (first[2]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): return first + 3; default: @@ -1698,23 +1429,8 @@ static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state case _UT('%'): return URI_FUNC(ParsePctEncoded)(state, first, afterLast, memory); - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('*'): - case _UT(','): - case _UT(';'): - case _UT('\''): - case _UT('+'): - case _UT('='): - case _UT('-'): - case _UT('.'): - case _UT('_'): - case _UT('~'): - case URI_SET_DIGIT: - case URI_SET_ALPHA: + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): return first + 1; default: @@ -1735,7 +1451,7 @@ static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, } switch (*first) { - case URI_SET_DIGIT: + case URI_SET_DIGIT(_UT): return URI_FUNC(ParsePort)(state, first + 1, afterLast); default: @@ -1758,26 +1474,7 @@ static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, } switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: { + case URI_SET_PCHAR(_UT): { const URI_CHAR * const afterPchar = URI_FUNC(ParsePchar)(state, first, afterLast, memory); if (afterPchar == NULL) { @@ -1808,26 +1505,7 @@ static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, } switch (*first) { - case _UT('!'): - case _UT('$'): - case _UT('%'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('-'): - case _UT('*'): - case _UT(','): - case _UT('.'): - case _UT(':'): - case _UT(';'): - case _UT('@'): - case _UT('\''): - case _UT('_'): - case _UT('~'): - case _UT('+'): - case _UT('='): - case URI_SET_DIGIT: - case URI_SET_ALPHA: { + case URI_SET_PCHAR(_UT): { const URI_CHAR * const afterPchar = URI_FUNC(ParsePchar)(state, first, afterLast, memory); if (afterPchar == NULL) { @@ -1906,8 +1584,8 @@ static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState case _UT('.'): case _UT('+'): case _UT('-'): - case URI_SET_ALPHA: - case URI_SET_DIGIT: + case URI_SET_ALPHA(_UT): + case URI_SET_DIGIT(_UT): return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast, memory); case _UT('%'): { @@ -2002,22 +1680,12 @@ static const URI_CHAR * URI_FUNC(ParseUriReference)(URI_TYPE(ParserState) * stat } switch (*first) { - case URI_SET_ALPHA: + case URI_SET_ALPHA(_UT): state->uri->scheme.first = first; /* SCHEME BEGIN */ return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast, memory); - case URI_SET_DIGIT: - case _UT('!'): - case _UT('$'): - case _UT('&'): - case _UT('('): - case _UT(')'): - case _UT('*'): - case _UT(','): - case _UT(';'): - case _UT('\''): - case _UT('+'): - case _UT('='): + case URI_SET_DIGIT(_UT): + case URI_SET_SUB_DELIMS(_UT): case _UT('.'): case _UT('_'): case _UT('~'): diff --git a/ext/uri/uriparser/src/UriSetFragment.c b/ext/uri/uriparser/src/UriSetFragment.c index b9c5c53b04202..4479391d859dc 100644 --- a/ext/uri/uriparser/src/UriSetFragment.c +++ b/ext/uri/uriparser/src/UriSetFragment.c @@ -62,104 +62,11 @@ # include # include "UriCommon.h" # include "UriMemory.h" +# include "UriSets.h" # endif # include -# define URI_SET_DIGIT \ - _UT('0') : case _UT('1'): \ - case _UT('2'): \ - case _UT('3'): \ - case _UT('4'): \ - case _UT('5'): \ - case _UT('6'): \ - case _UT('7'): \ - case _UT('8'): \ - case _UT('9') - -# define URI_SET_HEX_LETTER_UPPER \ - _UT('A') : case _UT('B'): \ - case _UT('C'): \ - case _UT('D'): \ - case _UT('E'): \ - case _UT('F') - -# define URI_SET_HEX_LETTER_LOWER \ - _UT('a') : case _UT('b'): \ - case _UT('c'): \ - case _UT('d'): \ - case _UT('e'): \ - case _UT('f') - -# define URI_SET_HEXDIG \ - URI_SET_DIGIT: \ - case URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER - -# define URI_SET_ALPHA \ - URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER: \ - case _UT('g'): \ - case _UT('G'): \ - case _UT('h'): \ - case _UT('H'): \ - case _UT('i'): \ - case _UT('I'): \ - case _UT('j'): \ - case _UT('J'): \ - case _UT('k'): \ - case _UT('K'): \ - case _UT('l'): \ - case _UT('L'): \ - case _UT('m'): \ - case _UT('M'): \ - case _UT('n'): \ - case _UT('N'): \ - case _UT('o'): \ - case _UT('O'): \ - case _UT('p'): \ - case _UT('P'): \ - case _UT('q'): \ - case _UT('Q'): \ - case _UT('r'): \ - case _UT('R'): \ - case _UT('s'): \ - case _UT('S'): \ - case _UT('t'): \ - case _UT('T'): \ - case _UT('u'): \ - case _UT('U'): \ - case _UT('v'): \ - case _UT('V'): \ - case _UT('w'): \ - case _UT('W'): \ - case _UT('x'): \ - case _UT('X'): \ - case _UT('y'): \ - case _UT('Y'): \ - case _UT('z'): \ - case _UT('Z') - -# define URI_SET_SUB_DELIMS \ - _UT('!') : case _UT('$'): \ - case _UT('&'): \ - case _UT('\''): \ - case _UT('('): \ - case _UT(')'): \ - case _UT('*'): \ - case _UT('+'): \ - case _UT(','): \ - case _UT(';'): \ - case _UT('=') - -# define URI_SET_UNRESERVED \ - URI_SET_ALPHA: \ - case URI_SET_DIGIT: \ - case _UT('-'): \ - case _UT('.'): \ - case _UT('_'): \ - case _UT('~') - UriBool URI_FUNC(IsWellFormedFragment)(const URI_CHAR * first, const URI_CHAR * afterLast) { if ((first == NULL) || (afterLast == NULL)) { @@ -173,7 +80,7 @@ UriBool URI_FUNC(IsWellFormedFragment)(const URI_CHAR * first, */ while (first < afterLast) { switch (first[0]) { - case URI_SET_UNRESERVED: + case URI_SET_PCHAR_WITHOUT_PERCENT(_UT): break; /* pct-encoded */ @@ -182,13 +89,13 @@ UriBool URI_FUNC(IsWellFormedFragment)(const URI_CHAR * first, return URI_FALSE; } switch (first[1]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): break; default: return URI_FALSE; } switch (first[2]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): break; default: return URI_FALSE; @@ -196,12 +103,6 @@ UriBool URI_FUNC(IsWellFormedFragment)(const URI_CHAR * first, first += 2; break; - case URI_SET_SUB_DELIMS: - break; - - /* ":" / "@" and "/" / "?" */ - case _UT(':'): - case _UT('@'): case _UT('/'): case _UT('?'): break; diff --git a/ext/uri/uriparser/src/UriSetHostRegName.c b/ext/uri/uriparser/src/UriSetHostRegName.c index 61694b248adc6..01bc4e47f16ef 100644 --- a/ext/uri/uriparser/src/UriSetHostRegName.c +++ b/ext/uri/uriparser/src/UriSetHostRegName.c @@ -63,102 +63,9 @@ # include "UriMemory.h" # include "UriSetHostBase.h" # include "UriSetHostCommon.h" +# include "UriSets.h" # endif -# define URI_SET_DIGIT \ - _UT('0') : case _UT('1'): \ - case _UT('2'): \ - case _UT('3'): \ - case _UT('4'): \ - case _UT('5'): \ - case _UT('6'): \ - case _UT('7'): \ - case _UT('8'): \ - case _UT('9') - -# define URI_SET_HEX_LETTER_UPPER \ - _UT('A') : case _UT('B'): \ - case _UT('C'): \ - case _UT('D'): \ - case _UT('E'): \ - case _UT('F') - -# define URI_SET_HEX_LETTER_LOWER \ - _UT('a') : case _UT('b'): \ - case _UT('c'): \ - case _UT('d'): \ - case _UT('e'): \ - case _UT('f') - -# define URI_SET_HEXDIG \ - URI_SET_DIGIT: \ - case URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER - -# define URI_SET_ALPHA \ - URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER: \ - case _UT('g'): \ - case _UT('G'): \ - case _UT('h'): \ - case _UT('H'): \ - case _UT('i'): \ - case _UT('I'): \ - case _UT('j'): \ - case _UT('J'): \ - case _UT('k'): \ - case _UT('K'): \ - case _UT('l'): \ - case _UT('L'): \ - case _UT('m'): \ - case _UT('M'): \ - case _UT('n'): \ - case _UT('N'): \ - case _UT('o'): \ - case _UT('O'): \ - case _UT('p'): \ - case _UT('P'): \ - case _UT('q'): \ - case _UT('Q'): \ - case _UT('r'): \ - case _UT('R'): \ - case _UT('s'): \ - case _UT('S'): \ - case _UT('t'): \ - case _UT('T'): \ - case _UT('u'): \ - case _UT('U'): \ - case _UT('v'): \ - case _UT('V'): \ - case _UT('w'): \ - case _UT('W'): \ - case _UT('x'): \ - case _UT('X'): \ - case _UT('y'): \ - case _UT('Y'): \ - case _UT('z'): \ - case _UT('Z') - -# define URI_SET_SUB_DELIMS \ - _UT('!') : case _UT('$'): \ - case _UT('&'): \ - case _UT('\''): \ - case _UT('('): \ - case _UT(')'): \ - case _UT('*'): \ - case _UT('+'): \ - case _UT(','): \ - case _UT(';'): \ - case _UT('=') - -# define URI_SET_UNRESERVED \ - URI_SET_ALPHA: \ - case URI_SET_DIGIT: \ - case _UT('-'): \ - case _UT('.'): \ - case _UT('_'): \ - case _UT('~') - UriBool URI_FUNC(IsWellFormedHostRegName)(const URI_CHAR * first, const URI_CHAR * afterLast) { if ((first == NULL) || (afterLast == NULL)) { @@ -168,7 +75,7 @@ UriBool URI_FUNC(IsWellFormedHostRegName)(const URI_CHAR * first, /* reg-name = *( unreserved / pct-encoded / sub-delims ) */ while (first < afterLast) { switch (first[0]) { - case URI_SET_UNRESERVED: + case URI_SET_UNRESERVED(_UT): break; /* pct-encoded */ @@ -177,13 +84,13 @@ UriBool URI_FUNC(IsWellFormedHostRegName)(const URI_CHAR * first, return URI_FALSE; } switch (first[1]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): break; default: return URI_FALSE; } switch (first[2]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): break; default: return URI_FALSE; @@ -191,7 +98,7 @@ UriBool URI_FUNC(IsWellFormedHostRegName)(const URI_CHAR * first, first += 2; break; - case URI_SET_SUB_DELIMS: + case URI_SET_SUB_DELIMS(_UT): break; default: diff --git a/ext/uri/uriparser/src/UriSetPath.c b/ext/uri/uriparser/src/UriSetPath.c index d9e8bec0aa802..17aef0fca42d4 100644 --- a/ext/uri/uriparser/src/UriSetPath.c +++ b/ext/uri/uriparser/src/UriSetPath.c @@ -62,104 +62,11 @@ # include # include "UriCommon.h" # include "UriMemory.h" +# include "UriSets.h" # endif # include -# define URI_SET_DIGIT \ - _UT('0') : case _UT('1'): \ - case _UT('2'): \ - case _UT('3'): \ - case _UT('4'): \ - case _UT('5'): \ - case _UT('6'): \ - case _UT('7'): \ - case _UT('8'): \ - case _UT('9') - -# define URI_SET_HEX_LETTER_UPPER \ - _UT('A') : case _UT('B'): \ - case _UT('C'): \ - case _UT('D'): \ - case _UT('E'): \ - case _UT('F') - -# define URI_SET_HEX_LETTER_LOWER \ - _UT('a') : case _UT('b'): \ - case _UT('c'): \ - case _UT('d'): \ - case _UT('e'): \ - case _UT('f') - -# define URI_SET_HEXDIG \ - URI_SET_DIGIT: \ - case URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER - -# define URI_SET_ALPHA \ - URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER: \ - case _UT('g'): \ - case _UT('G'): \ - case _UT('h'): \ - case _UT('H'): \ - case _UT('i'): \ - case _UT('I'): \ - case _UT('j'): \ - case _UT('J'): \ - case _UT('k'): \ - case _UT('K'): \ - case _UT('l'): \ - case _UT('L'): \ - case _UT('m'): \ - case _UT('M'): \ - case _UT('n'): \ - case _UT('N'): \ - case _UT('o'): \ - case _UT('O'): \ - case _UT('p'): \ - case _UT('P'): \ - case _UT('q'): \ - case _UT('Q'): \ - case _UT('r'): \ - case _UT('R'): \ - case _UT('s'): \ - case _UT('S'): \ - case _UT('t'): \ - case _UT('T'): \ - case _UT('u'): \ - case _UT('U'): \ - case _UT('v'): \ - case _UT('V'): \ - case _UT('w'): \ - case _UT('W'): \ - case _UT('x'): \ - case _UT('X'): \ - case _UT('y'): \ - case _UT('Y'): \ - case _UT('z'): \ - case _UT('Z') - -# define URI_SET_SUB_DELIMS \ - _UT('!') : case _UT('$'): \ - case _UT('&'): \ - case _UT('\''): \ - case _UT('('): \ - case _UT(')'): \ - case _UT('*'): \ - case _UT('+'): \ - case _UT(','): \ - case _UT(';'): \ - case _UT('=') - -# define URI_SET_UNRESERVED \ - URI_SET_ALPHA: \ - case URI_SET_DIGIT: \ - case _UT('-'): \ - case _UT('.'): \ - case _UT('_'): \ - case _UT('~') - UriBool URI_FUNC(IsWellFormedPath)(const URI_CHAR * first, const URI_CHAR * afterLast, UriBool hasHost) { if ((first == NULL) || (afterLast == NULL)) { @@ -200,7 +107,7 @@ UriBool URI_FUNC(IsWellFormedPath)(const URI_CHAR * first, const URI_CHAR * afte */ while (first < afterLast) { switch (first[0]) { - case URI_SET_UNRESERVED: + case URI_SET_PCHAR_WITHOUT_PERCENT(_UT): break; /* pct-encoded */ @@ -209,13 +116,13 @@ UriBool URI_FUNC(IsWellFormedPath)(const URI_CHAR * first, const URI_CHAR * afte return URI_FALSE; } switch (first[1]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): break; default: return URI_FALSE; } switch (first[2]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): break; default: return URI_FALSE; @@ -223,12 +130,6 @@ UriBool URI_FUNC(IsWellFormedPath)(const URI_CHAR * first, const URI_CHAR * afte first += 2; break; - case URI_SET_SUB_DELIMS: - break; - - /* ":" / "@" and "/" */ - case _UT(':'): - case _UT('@'): case _UT('/'): break; diff --git a/ext/uri/uriparser/src/UriSetPort.c b/ext/uri/uriparser/src/UriSetPort.c index 1c373013f66d0..5e2160e309765 100644 --- a/ext/uri/uriparser/src/UriSetPort.c +++ b/ext/uri/uriparser/src/UriSetPort.c @@ -62,21 +62,11 @@ # include # include "UriCommon.h" # include "UriMemory.h" +# include "UriSets.h" # endif # include -# define URI_SET_DIGIT \ - _UT('0') : case _UT('1'): \ - case _UT('2'): \ - case _UT('3'): \ - case _UT('4'): \ - case _UT('5'): \ - case _UT('6'): \ - case _UT('7'): \ - case _UT('8'): \ - case _UT('9') - UriBool URI_FUNC(IsWellFormedPort)(const URI_CHAR * first, const URI_CHAR * afterLast) { if ((first == NULL) || (afterLast == NULL)) { return URI_FALSE; @@ -85,7 +75,7 @@ UriBool URI_FUNC(IsWellFormedPort)(const URI_CHAR * first, const URI_CHAR * afte /* NOTE: Grammar reads "port = *DIGIT" which includes the empty string. */ while (first < afterLast) { switch (first[0]) { - case URI_SET_DIGIT: + case URI_SET_DIGIT(_UT): break; default: return URI_FALSE; diff --git a/ext/uri/uriparser/src/UriSetQuery.c b/ext/uri/uriparser/src/UriSetQuery.c index a189c14bb1ed9..4f58c8286ed70 100644 --- a/ext/uri/uriparser/src/UriSetQuery.c +++ b/ext/uri/uriparser/src/UriSetQuery.c @@ -62,104 +62,11 @@ # include # include "UriCommon.h" # include "UriMemory.h" +# include "UriSets.h" # endif # include -# define URI_SET_DIGIT \ - _UT('0') : case _UT('1'): \ - case _UT('2'): \ - case _UT('3'): \ - case _UT('4'): \ - case _UT('5'): \ - case _UT('6'): \ - case _UT('7'): \ - case _UT('8'): \ - case _UT('9') - -# define URI_SET_HEX_LETTER_UPPER \ - _UT('A') : case _UT('B'): \ - case _UT('C'): \ - case _UT('D'): \ - case _UT('E'): \ - case _UT('F') - -# define URI_SET_HEX_LETTER_LOWER \ - _UT('a') : case _UT('b'): \ - case _UT('c'): \ - case _UT('d'): \ - case _UT('e'): \ - case _UT('f') - -# define URI_SET_HEXDIG \ - URI_SET_DIGIT: \ - case URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER - -# define URI_SET_ALPHA \ - URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER: \ - case _UT('g'): \ - case _UT('G'): \ - case _UT('h'): \ - case _UT('H'): \ - case _UT('i'): \ - case _UT('I'): \ - case _UT('j'): \ - case _UT('J'): \ - case _UT('k'): \ - case _UT('K'): \ - case _UT('l'): \ - case _UT('L'): \ - case _UT('m'): \ - case _UT('M'): \ - case _UT('n'): \ - case _UT('N'): \ - case _UT('o'): \ - case _UT('O'): \ - case _UT('p'): \ - case _UT('P'): \ - case _UT('q'): \ - case _UT('Q'): \ - case _UT('r'): \ - case _UT('R'): \ - case _UT('s'): \ - case _UT('S'): \ - case _UT('t'): \ - case _UT('T'): \ - case _UT('u'): \ - case _UT('U'): \ - case _UT('v'): \ - case _UT('V'): \ - case _UT('w'): \ - case _UT('W'): \ - case _UT('x'): \ - case _UT('X'): \ - case _UT('y'): \ - case _UT('Y'): \ - case _UT('z'): \ - case _UT('Z') - -# define URI_SET_SUB_DELIMS \ - _UT('!') : case _UT('$'): \ - case _UT('&'): \ - case _UT('\''): \ - case _UT('('): \ - case _UT(')'): \ - case _UT('*'): \ - case _UT('+'): \ - case _UT(','): \ - case _UT(';'): \ - case _UT('=') - -# define URI_SET_UNRESERVED \ - URI_SET_ALPHA: \ - case URI_SET_DIGIT: \ - case _UT('-'): \ - case _UT('.'): \ - case _UT('_'): \ - case _UT('~') - UriBool URI_FUNC(IsWellFormedQuery)(const URI_CHAR * first, const URI_CHAR * afterLast) { if ((first == NULL) || (afterLast == NULL)) { return URI_FALSE; @@ -172,7 +79,7 @@ UriBool URI_FUNC(IsWellFormedQuery)(const URI_CHAR * first, const URI_CHAR * aft */ while (first < afterLast) { switch (first[0]) { - case URI_SET_UNRESERVED: + case URI_SET_PCHAR_WITHOUT_PERCENT(_UT): break; /* pct-encoded */ @@ -181,13 +88,13 @@ UriBool URI_FUNC(IsWellFormedQuery)(const URI_CHAR * first, const URI_CHAR * aft return URI_FALSE; } switch (first[1]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): break; default: return URI_FALSE; } switch (first[2]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): break; default: return URI_FALSE; @@ -195,12 +102,6 @@ UriBool URI_FUNC(IsWellFormedQuery)(const URI_CHAR * first, const URI_CHAR * aft first += 2; break; - case URI_SET_SUB_DELIMS: - break; - - /* ":" / "@" and "/" / "?" */ - case _UT(':'): - case _UT('@'): case _UT('/'): case _UT('?'): break; diff --git a/ext/uri/uriparser/src/UriSetScheme.c b/ext/uri/uriparser/src/UriSetScheme.c index 9a21d45f26319..3dfaf1e9f151b 100644 --- a/ext/uri/uriparser/src/UriSetScheme.c +++ b/ext/uri/uriparser/src/UriSetScheme.c @@ -62,84 +62,11 @@ # include # include "UriCommon.h" # include "UriMemory.h" +# include "UriSets.h" # endif # include -# define URI_SET_DIGIT \ - _UT('0') : case _UT('1'): \ - case _UT('2'): \ - case _UT('3'): \ - case _UT('4'): \ - case _UT('5'): \ - case _UT('6'): \ - case _UT('7'): \ - case _UT('8'): \ - case _UT('9') - -# define URI_SET_HEX_LETTER_UPPER \ - _UT('A') : case _UT('B'): \ - case _UT('C'): \ - case _UT('D'): \ - case _UT('E'): \ - case _UT('F') - -# define URI_SET_HEX_LETTER_LOWER \ - _UT('a') : case _UT('b'): \ - case _UT('c'): \ - case _UT('d'): \ - case _UT('e'): \ - case _UT('f') - -# define URI_SET_HEXDIG \ - URI_SET_DIGIT: \ - case URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER - -# define URI_SET_ALPHA \ - URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER: \ - case _UT('g'): \ - case _UT('G'): \ - case _UT('h'): \ - case _UT('H'): \ - case _UT('i'): \ - case _UT('I'): \ - case _UT('j'): \ - case _UT('J'): \ - case _UT('k'): \ - case _UT('K'): \ - case _UT('l'): \ - case _UT('L'): \ - case _UT('m'): \ - case _UT('M'): \ - case _UT('n'): \ - case _UT('N'): \ - case _UT('o'): \ - case _UT('O'): \ - case _UT('p'): \ - case _UT('P'): \ - case _UT('q'): \ - case _UT('Q'): \ - case _UT('r'): \ - case _UT('R'): \ - case _UT('s'): \ - case _UT('S'): \ - case _UT('t'): \ - case _UT('T'): \ - case _UT('u'): \ - case _UT('U'): \ - case _UT('v'): \ - case _UT('V'): \ - case _UT('w'): \ - case _UT('W'): \ - case _UT('x'): \ - case _UT('X'): \ - case _UT('y'): \ - case _UT('Y'): \ - case _UT('z'): \ - case _UT('Z') - UriBool URI_FUNC(IsWellFormedScheme)(const URI_CHAR * first, const URI_CHAR * afterLast) { if ((first == NULL) || (afterLast == NULL)) { return URI_FALSE; @@ -154,7 +81,7 @@ UriBool URI_FUNC(IsWellFormedScheme)(const URI_CHAR * first, const URI_CHAR * af } switch (first[0]) { - case URI_SET_ALPHA: + case URI_SET_ALPHA(_UT): break; default: @@ -165,8 +92,8 @@ UriBool URI_FUNC(IsWellFormedScheme)(const URI_CHAR * first, const URI_CHAR * af while (first < afterLast) { switch (first[0]) { - case URI_SET_ALPHA: - case URI_SET_DIGIT: + case URI_SET_ALPHA(_UT): + case URI_SET_DIGIT(_UT): case _UT('+'): case _UT('-'): case _UT('.'): diff --git a/ext/uri/uriparser/src/UriSetUserInfo.c b/ext/uri/uriparser/src/UriSetUserInfo.c index af1ec41a0763d..7865e837deb66 100644 --- a/ext/uri/uriparser/src/UriSetUserInfo.c +++ b/ext/uri/uriparser/src/UriSetUserInfo.c @@ -62,104 +62,11 @@ # include # include "UriCommon.h" # include "UriMemory.h" +# include "UriSets.h" # endif # include -# define URI_SET_DIGIT \ - _UT('0') : case _UT('1'): \ - case _UT('2'): \ - case _UT('3'): \ - case _UT('4'): \ - case _UT('5'): \ - case _UT('6'): \ - case _UT('7'): \ - case _UT('8'): \ - case _UT('9') - -# define URI_SET_HEX_LETTER_UPPER \ - _UT('A') : case _UT('B'): \ - case _UT('C'): \ - case _UT('D'): \ - case _UT('E'): \ - case _UT('F') - -# define URI_SET_HEX_LETTER_LOWER \ - _UT('a') : case _UT('b'): \ - case _UT('c'): \ - case _UT('d'): \ - case _UT('e'): \ - case _UT('f') - -# define URI_SET_HEXDIG \ - URI_SET_DIGIT: \ - case URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER - -# define URI_SET_ALPHA \ - URI_SET_HEX_LETTER_UPPER: \ - case URI_SET_HEX_LETTER_LOWER: \ - case _UT('g'): \ - case _UT('G'): \ - case _UT('h'): \ - case _UT('H'): \ - case _UT('i'): \ - case _UT('I'): \ - case _UT('j'): \ - case _UT('J'): \ - case _UT('k'): \ - case _UT('K'): \ - case _UT('l'): \ - case _UT('L'): \ - case _UT('m'): \ - case _UT('M'): \ - case _UT('n'): \ - case _UT('N'): \ - case _UT('o'): \ - case _UT('O'): \ - case _UT('p'): \ - case _UT('P'): \ - case _UT('q'): \ - case _UT('Q'): \ - case _UT('r'): \ - case _UT('R'): \ - case _UT('s'): \ - case _UT('S'): \ - case _UT('t'): \ - case _UT('T'): \ - case _UT('u'): \ - case _UT('U'): \ - case _UT('v'): \ - case _UT('V'): \ - case _UT('w'): \ - case _UT('W'): \ - case _UT('x'): \ - case _UT('X'): \ - case _UT('y'): \ - case _UT('Y'): \ - case _UT('z'): \ - case _UT('Z') - -# define URI_SET_SUB_DELIMS \ - _UT('!') : case _UT('$'): \ - case _UT('&'): \ - case _UT('\''): \ - case _UT('('): \ - case _UT(')'): \ - case _UT('*'): \ - case _UT('+'): \ - case _UT(','): \ - case _UT(';'): \ - case _UT('=') - -# define URI_SET_UNRESERVED \ - URI_SET_ALPHA: \ - case URI_SET_DIGIT: \ - case _UT('-'): \ - case _UT('.'): \ - case _UT('_'): \ - case _UT('~') - UriBool URI_FUNC(IsWellFormedUserInfo)(const URI_CHAR * first, const URI_CHAR * afterLast) { if ((first == NULL) || (afterLast == NULL)) { @@ -169,7 +76,7 @@ UriBool URI_FUNC(IsWellFormedUserInfo)(const URI_CHAR * first, /* userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) */ while (first < afterLast) { switch (first[0]) { - case URI_SET_UNRESERVED: + case URI_SET_UNRESERVED(_UT): break; /* pct-encoded */ @@ -178,13 +85,13 @@ UriBool URI_FUNC(IsWellFormedUserInfo)(const URI_CHAR * first, return URI_FALSE; } switch (first[1]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): break; default: return URI_FALSE; } switch (first[2]) { - case URI_SET_HEXDIG: + case URI_SET_HEXDIG(_UT): break; default: return URI_FALSE; @@ -192,7 +99,7 @@ UriBool URI_FUNC(IsWellFormedUserInfo)(const URI_CHAR * first, first += 2; break; - case URI_SET_SUB_DELIMS: + case URI_SET_SUB_DELIMS(_UT): break; /* ":" */ diff --git a/ext/uri/uriparser/src/UriSets.h b/ext/uri/uriparser/src/UriSets.h new file mode 100644 index 0000000000000..a6a2c46a14d77 --- /dev/null +++ b/ext/uri/uriparser/src/UriSets.h @@ -0,0 +1,174 @@ +/* + * uriparser - RFC 3986 URI parsing library + * + * Copyright (C) 2025, Sebastian Pipping + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of + * its contributors may be used to endorse or promote products + * derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file UriSets.h + * Holds character set definitions. + */ + +// NOTE: We cannot use a regular include-once guard here because the +// file must support being included twice, e.g. from file UriParse.c. +#if !defined(URI_SET_DIGIT) + +// clang-format off +# define URI_SET_DIGIT(ut) \ + ut('0'): \ + case ut('1'): \ + /* clang-format on */ \ + case ut('2'): \ + case ut('3'): \ + case ut('4'): \ + case ut('5'): \ + case ut('6'): \ + case ut('7'): \ + case ut('8'): \ + case ut('9') + +// clang-format off +# define URI_SET_HEX_LETTER_LOWER(ut) \ + ut('a'): \ + case ut('b'): \ + /* clang-format on */ \ + case ut('c'): \ + case ut('d'): \ + case ut('e'): \ + case ut('f') + +// clang-format off +# define URI_SET_HEX_LETTER_UPPER(ut) \ + ut('A'): \ + case ut('B'): \ + /* clang-format on */ \ + case ut('C'): \ + case ut('D'): \ + case ut('E'): \ + case ut('F') + +// clang-format off +# define URI_SET_HEXDIG(ut) \ + URI_SET_DIGIT(ut): \ + case URI_SET_HEX_LETTER_LOWER(ut): \ + /* clang-format on */ \ + case URI_SET_HEX_LETTER_UPPER(ut) + +// clang-format off +# define URI_SET_ALPHA(ut) \ + URI_SET_HEX_LETTER_UPPER(ut): \ + case URI_SET_HEX_LETTER_LOWER(ut): \ + /* clang-format on */ \ + case ut('g'): \ + case ut('G'): \ + case ut('h'): \ + case ut('H'): \ + case ut('i'): \ + case ut('I'): \ + case ut('j'): \ + case ut('J'): \ + case ut('k'): \ + case ut('K'): \ + case ut('l'): \ + case ut('L'): \ + case ut('m'): \ + case ut('M'): \ + case ut('n'): \ + case ut('N'): \ + case ut('o'): \ + case ut('O'): \ + case ut('p'): \ + case ut('P'): \ + case ut('q'): \ + case ut('Q'): \ + case ut('r'): \ + case ut('R'): \ + case ut('s'): \ + case ut('S'): \ + case ut('t'): \ + case ut('T'): \ + case ut('u'): \ + case ut('U'): \ + case ut('v'): \ + case ut('V'): \ + case ut('w'): \ + case ut('W'): \ + case ut('x'): \ + case ut('X'): \ + case ut('y'): \ + case ut('Y'): \ + case ut('z'): \ + case ut('Z') + +// clang-format off +# define URI_SET_SUB_DELIMS(ut) \ + ut('!'): \ + case ut('$'): \ + /* clang-format on */ \ + case ut('&'): \ + case ut('\''): \ + case ut('('): \ + case ut(')'): \ + case ut('*'): \ + case ut('+'): \ + case ut(','): \ + case ut(';'): \ + case ut('=') + +// clang-format off +# define URI_SET_UNRESERVED(ut) \ + URI_SET_ALPHA(ut): \ + case URI_SET_DIGIT(ut): \ + /* clang-format on */ \ + case ut('-'): \ + case ut('.'): \ + case ut('_'): \ + case ut('~') + +// clang-format off +# define URI_SET_PCHAR_WITHOUT_PERCENT(ut) \ + URI_SET_UNRESERVED(ut): \ + case URI_SET_SUB_DELIMS(ut): \ + /* clang-format on */ \ + case ut(':'): \ + case ut('@') + +// clang-format off +# define URI_SET_PCHAR(ut) \ + URI_SET_PCHAR_WITHOUT_PERCENT(ut): \ + case ut('%') +/* clang-format on */ + +#endif // ! defined(URI_SET_DIGIT) From b9d726848219c86cec107faf8c7097e44b9e9b8a Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Wed, 26 Nov 2025 11:43:34 +0000 Subject: [PATCH 03/12] Fix GH-20553: PDO::FETCH_CLASSTYPE ignores $constructorArgs in PHP 8.5.0 We must assign the ctor_arguments regardless of modes. This regression was introduced during the refactoring of PDO's internals Closes GH-20595 --- ext/pdo/pdo_stmt.c | 3 +- ext/pdo/tests/gh20553.phpt | 97 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 ext/pdo/tests/gh20553.phpt diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 697940d94260d..5d8b4089ca04f 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -771,9 +771,10 @@ static bool do_fetch(pdo_stmt_t *stmt, zval *return_value, enum pdo_fetch_type h pdo_raise_impl_error(stmt->dbh, stmt, "HY000", "No fetch class specified"); goto in_fetch_error; } - ctor_arguments = stmt->fetch.cls.ctor_args; } ZEND_ASSERT(ce != NULL); + + ctor_arguments = stmt->fetch.cls.ctor_args; if (flags & PDO_FETCH_SERIALIZE) { if (!ce->unserialize) { /* As this option is deprecated we do not bother to mention the class name. */ diff --git a/ext/pdo/tests/gh20553.phpt b/ext/pdo/tests/gh20553.phpt new file mode 100644 index 0000000000000..fe0b84c27ebb0 --- /dev/null +++ b/ext/pdo/tests/gh20553.phpt @@ -0,0 +1,97 @@ +--TEST-- +GH-20553: PHP 8.5.0 regression: PDO::FETCH_CLASSTYPE ignores $constructorArgs +--EXTENSIONS-- +pdo +--SKIPIF-- + +--FILE-- + PDO::FETCH_CLASS, + 'PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE' + => PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, + 'PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE' + => PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE, + 'PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE | PDO::FETCH_PROPS_LATE' + => PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE | PDO::FETCH_PROPS_LATE, +]; + +foreach ($fetchModes as $combinedModes => $fetchMode) { + echo '## ' . $combinedModes . PHP_EOL; + $db->query($sql)->fetchAll( + $fetchMode, + 'dumpy', + ['constructor argument #1'] + ); + echo PHP_EOL; +} +?> +--EXPECT-- +## PDO::FETCH_CLASS +'pdo_fetch_class_type_class' = 'dummy' +'foo' = 'bar' +'abc' = 'dfg' +constructor called, + my class is 'dumpy' + input parameters: array ( + 0 => 'constructor argument #1', +) + +## PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE +constructor called, + my class is 'dumpy' + input parameters: array ( + 0 => 'constructor argument #1', +) +'pdo_fetch_class_type_class' = 'dummy' +'foo' = 'bar' +'abc' = 'dfg' + +## PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE +'foo' = 'bar' +'abc' = 'dfg' +constructor called, + my class is 'dummy' + input parameters: array ( + 0 => 'constructor argument #1', +) + +## PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE | PDO::FETCH_PROPS_LATE +constructor called, + my class is 'dummy' + input parameters: array ( + 0 => 'constructor argument #1', +) +'foo' = 'bar' +'abc' = 'dfg' From eb617f32bbc125b93a62d4e3da738a808c735653 Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Tue, 9 Dec 2025 14:56:07 +0100 Subject: [PATCH 04/12] Update news after cherry-picks --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index b89c399f3fee4..d1ffa9e35f5bd 100644 --- a/NEWS +++ b/NEWS @@ -48,6 +48,10 @@ PHP NEWS . Fixed bug GH-20329 (opcache.file_cache broken with full interned string buffer). (Arnaud) +- PDO: + . Fixed bug GH-20553 (PDO::FETCH_CLASSTYPE ignores $constructorArgs in + PHP 8.5.0). (Girgias) + - Phar: . Fixed bug GH-20442 (Phar does not respect case-insensitiveness of __halt_compiler() when reading stub). (ndossche, TimWolla) From 501b15ecbfa7a2406abe84501f65ebd1134ce9aa Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sat, 11 Oct 2025 19:37:26 +0200 Subject: [PATCH 05/12] Fix GHSA-8xr5-qppj-gvwj: PDO quoting result null deref --- ext/pdo/pdo_sql_parser.re | 6 +++++ ext/pdo_pgsql/tests/ghsa-8xr5-qppj-gvwj.phpt | 28 ++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 ext/pdo_pgsql/tests/ghsa-8xr5-qppj-gvwj.phpt diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re index a87fd473404ec..1897f9f238bf1 100644 --- a/ext/pdo/pdo_sql_parser.re +++ b/ext/pdo/pdo_sql_parser.re @@ -300,6 +300,12 @@ safe: } plc->quoted = stmt->dbh->methods->quoter(stmt->dbh, buf, param_type); + if (plc->quoted == NULL) { + /* bork */ + ret = -1; + strncpy(stmt->error_code, stmt->dbh->error_code, 6); + goto clean_up; + } } } diff --git a/ext/pdo_pgsql/tests/ghsa-8xr5-qppj-gvwj.phpt b/ext/pdo_pgsql/tests/ghsa-8xr5-qppj-gvwj.phpt new file mode 100644 index 0000000000000..736354cab13cb --- /dev/null +++ b/ext/pdo_pgsql/tests/ghsa-8xr5-qppj-gvwj.phpt @@ -0,0 +1,28 @@ +--TEST-- +#GHSA-8xr5-qppj-gvwj: NULL Pointer Derefernce for failed user input quoting +--EXTENSIONS-- +pdo +pdo_pgsql +--SKIPIF-- + +--FILE-- +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true); + +$sql = "SELECT * FROM users where username = :username"; +$stmt = $db->prepare($sql); + +$p1 = "alice\x99"; +var_dump($stmt->execute(['username' => $p1])); + +?> +--EXPECT-- +bool(false) From a7f2a15c5bcae1ce181b016c438b84f3d5761a6b Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 9 Nov 2025 13:23:11 +0100 Subject: [PATCH 06/12] Fix GHSA-h96m-rvf9-jgm2 --- ext/standard/array.c | 7 ++++++- .../tests/array/GHSA-h96m-rvf9-jgm2.phpt | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/array/GHSA-h96m-rvf9-jgm2.phpt diff --git a/ext/standard/array.c b/ext/standard/array.c index 44d226b2d822a..b148bcf356897 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -4272,7 +4272,7 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET uint32_t argc, i; zval *src_entry; HashTable *src, *dest; - uint32_t count = 0; + uint64_t count = 0; ZEND_PARSE_PARAMETERS_START(0, -1) Z_PARAM_VARIADIC('+', args, argc) @@ -4292,6 +4292,11 @@ static zend_always_inline void php_array_merge_wrapper(INTERNAL_FUNCTION_PARAMET count += zend_hash_num_elements(Z_ARRVAL_P(arg)); } + if (UNEXPECTED(count >= HT_MAX_SIZE)) { + zend_throw_error(NULL, "The total number of elements must be lower than %u", HT_MAX_SIZE); + RETURN_THROWS(); + } + if (argc == 2) { zval *ret = NULL; diff --git a/ext/standard/tests/array/GHSA-h96m-rvf9-jgm2.phpt b/ext/standard/tests/array/GHSA-h96m-rvf9-jgm2.phpt new file mode 100644 index 0000000000000..2e3e85357e13c --- /dev/null +++ b/ext/standard/tests/array/GHSA-h96m-rvf9-jgm2.phpt @@ -0,0 +1,16 @@ +--TEST-- +GHSA-h96m-rvf9-jgm2 +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECTF-- +The total number of elements must be lower than %d From 6ba83131aafae1f0c5e2e7dc2c23beb5f9523323 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 6 Sep 2025 21:55:13 +0200 Subject: [PATCH 07/12] Fix GHSA-www2-q4fc-65wf --- ext/standard/basic_functions.c | 12 ++-- ext/standard/dns.c | 6 +- ext/standard/dns_win32.c | 6 +- .../tests/network/ghsa-www2-q4fc-65wf.phpt | 62 +++++++++++++++++++ 4 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 ext/standard/tests/network/ghsa-www2-q4fc-65wf.phpt diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index e0c4230dae27c..8b72ffffc8379 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -561,7 +561,7 @@ PHP_FUNCTION(inet_pton) char buffer[17]; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(address, address_len) + Z_PARAM_PATH(address, address_len) ZEND_PARSE_PARAMETERS_END(); memset(buffer, 0, sizeof(buffer)); @@ -593,7 +593,7 @@ PHP_FUNCTION(ip2long) struct in_addr ip; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(addr, addr_len) + Z_PARAM_PATH(addr, addr_len) ZEND_PARSE_PARAMETERS_END(); if (addr_len == 0 || inet_pton(AF_INET, addr, &ip) != 1) { @@ -2139,8 +2139,8 @@ PHP_FUNCTION(getservbyname) struct servent *serv; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STR(name) - Z_PARAM_STRING(proto, proto_len) + Z_PARAM_PATH_STR(name) + Z_PARAM_PATH(proto, proto_len) ZEND_PARSE_PARAMETERS_END(); @@ -2183,7 +2183,7 @@ PHP_FUNCTION(getservbyport) ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_LONG(port) - Z_PARAM_STRING(proto, proto_len) + Z_PARAM_PATH(proto, proto_len) ZEND_PARSE_PARAMETERS_END(); serv = getservbyport(htons((unsigned short) port), proto); @@ -2210,7 +2210,7 @@ PHP_FUNCTION(getprotobyname) struct protoent *ent; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_STRING(name, name_len) + Z_PARAM_PATH(name, name_len) ZEND_PARSE_PARAMETERS_END(); ent = getprotobyname(name); diff --git a/ext/standard/dns.c b/ext/standard/dns.c index bd5720210fdaf..a574d8dd9aeb8 100644 --- a/ext/standard/dns.c +++ b/ext/standard/dns.c @@ -382,7 +382,7 @@ PHP_FUNCTION(dns_check_record) #endif ZEND_PARSE_PARAMETERS_START(1, 2) - Z_PARAM_STRING(hostname, hostname_len) + Z_PARAM_PATH(hostname, hostname_len) Z_PARAM_OPTIONAL Z_PARAM_STR(rectype) ZEND_PARSE_PARAMETERS_END(); @@ -829,7 +829,7 @@ PHP_FUNCTION(dns_get_record) bool raw = 0; ZEND_PARSE_PARAMETERS_START(1, 5) - Z_PARAM_STRING(hostname, hostname_len) + Z_PARAM_PATH(hostname, hostname_len) Z_PARAM_OPTIONAL Z_PARAM_LONG(type_param) Z_PARAM_ZVAL(authns) @@ -1067,7 +1067,7 @@ PHP_FUNCTION(dns_get_mx) #endif ZEND_PARSE_PARAMETERS_START(2, 3) - Z_PARAM_STRING(hostname, hostname_len) + Z_PARAM_PATH(hostname, hostname_len) Z_PARAM_ZVAL(mx_list) Z_PARAM_OPTIONAL Z_PARAM_ZVAL(weight_list) diff --git a/ext/standard/dns_win32.c b/ext/standard/dns_win32.c index 26c6487902e1a..10ba1701a2c78 100644 --- a/ext/standard/dns_win32.c +++ b/ext/standard/dns_win32.c @@ -32,7 +32,7 @@ PHP_FUNCTION(dns_get_mx) /* {{{ */ DNS_STATUS status; /* Return value of DnsQuery_A() function */ PDNS_RECORD pResult, pRec; /* Pointer to DNS_RECORD structure */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sz|z", &hostname, &hostname_len, &mx_list, &weight_list) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "pz|z", &hostname, &hostname_len, &mx_list, &weight_list) == FAILURE) { RETURN_THROWS(); } @@ -86,7 +86,7 @@ PHP_FUNCTION(dns_check_record) DNS_STATUS status; /* Return value of DnsQuery_A() function */ PDNS_RECORD pResult; /* Pointer to DNS_RECORD structure */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|S", &hostname, &hostname_len, &rectype) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|S", &hostname, &hostname_len, &rectype) == FAILURE) { RETURN_THROWS(); } @@ -343,7 +343,7 @@ PHP_FUNCTION(dns_get_record) int type, type_to_fetch, first_query = 1, store_results = 1; bool raw = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lz!z!b", + if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|lz!z!b", &hostname, &hostname_len, &type_param, &authns, &addtl, &raw) == FAILURE) { RETURN_THROWS(); } diff --git a/ext/standard/tests/network/ghsa-www2-q4fc-65wf.phpt b/ext/standard/tests/network/ghsa-www2-q4fc-65wf.phpt new file mode 100644 index 0000000000000..3d082c8e95226 --- /dev/null +++ b/ext/standard/tests/network/ghsa-www2-q4fc-65wf.phpt @@ -0,0 +1,62 @@ +--TEST-- +GHSA-www2-q4fc-65wf +--DESCRIPTION-- +This is a ZPP test but *keep* this as it is security-sensitive! +--FILE-- +getMessage(), "\n"; +} +try { + dns_get_mx("\0", $out); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + dns_get_record("\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + getprotobyname("\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + getservbyname("\0", "tcp"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + getservbyname("x", "tcp\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + getservbyport(0, "tcp\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + inet_pton("\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +try { + ip2long("\0"); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} +?> +--EXPECT-- +dns_check_record(): Argument #1 ($hostname) must not contain any null bytes +dns_get_mx(): Argument #1 ($hostname) must not contain any null bytes +dns_get_record(): Argument #1 ($hostname) must not contain any null bytes +getprotobyname(): Argument #1 ($protocol) must not contain any null bytes +getservbyname(): Argument #1 ($service) must not contain any null bytes +getservbyname(): Argument #2 ($protocol) must not contain any null bytes +getservbyport(): Argument #2 ($protocol) must not contain any null bytes +inet_pton(): Argument #1 ($ip) must not contain any null bytes +ip2long(): Argument #1 ($ip) must not contain any null bytes From 9f903fbca520c5b02ddce0b515f3c6cdb4909f78 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 12 Dec 2025 13:48:19 +0100 Subject: [PATCH 08/12] Update NEWS with info about security issues --- NEWS | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index d1ffa9e35f5bd..b6073275fe92c 100644 --- a/NEWS +++ b/NEWS @@ -51,6 +51,8 @@ PHP NEWS - PDO: . Fixed bug GH-20553 (PDO::FETCH_CLASSTYPE ignores $constructorArgs in PHP 8.5.0). (Girgias) + . Fixed GHSA-8xr5-qppj-gvwj (PDO quoting result null deref). (CVE-2025-14180) + (Jakub Zelenka) - Phar: . Fixed bug GH-20442 (Phar does not respect case-insensitiveness of @@ -70,7 +72,12 @@ PHP NEWS . Fix memory leak in array_diff() with custom type checks. (ndossche) . Fixed bug GH-20583 (Stack overflow in http_build_query via deep structures). (ndossche) - . Fixed bug GH-20584 (Information Leak of Memory). (ndossche) + . Fixed GHSA-www2-q4fc-65wf (Null byte termination in dns_get_record()). + (ndossche) + . Fixed GHSA-h96m-rvf9-jgm2 (Heap buffer overflow in array_merge()). + (CVE-2025-14178) (ndossche) + . Fixed GHSA-3237-qqm7-mfv7 (Information Leak of Memory in getimagesize). + (CVE-2025-14177) (ndossche) - XML: . Fixed bug GH-20439 (xml_set_default_handler() does not properly handle From 1754cdc03311fd4020e5e1e08c9034599735f4c3 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 2 Dec 2025 16:26:50 +0100 Subject: [PATCH 09/12] Suppress libxml deprecations Closes GH-20538 --- ext/dom/document.c | 12 ++++++++++++ ext/dom/xml_serializer.c | 5 ++++- ext/libxml/libxml.c | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/ext/dom/document.c b/ext/dom/document.c index edf83939bf801..97215dfd270e3 100644 --- a/ext/dom/document.c +++ b/ext/dom/document.c @@ -1595,12 +1595,16 @@ PHP_METHOD(DOMDocument, save) libxml_doc_props const* doc_props = dom_get_doc_props_read_only(intern->document); bool format = doc_props->formatoutput; if (options & LIBXML_SAVE_NOEMPTYTAG) { + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") saveempty = xmlSaveNoEmptyTags; xmlSaveNoEmptyTags = 1; + ZEND_DIAGNOSTIC_IGNORED_END } zend_long bytes = intern->document->handlers->dump_doc_to_file(file, docp, format, (const char *) docp->encoding); if (options & LIBXML_SAVE_NOEMPTYTAG) { + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") xmlSaveNoEmptyTags = saveempty; + ZEND_DIAGNOSTIC_IGNORED_END } if (bytes == -1) { RETURN_FALSE; @@ -1641,10 +1645,14 @@ static void dom_document_save_xml(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry /* Save libxml2 global, override its value, and restore after saving (don't move me or risk breaking the state * w.r.t. the implicit return in DOM_GET_OBJ). */ + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") old_xml_save_no_empty_tags = xmlSaveNoEmptyTags; xmlSaveNoEmptyTags = (options & LIBXML_SAVE_NOEMPTYTAG) ? 1 : 0; + ZEND_DIAGNOSTIC_IGNORED_END res = intern->document->handlers->dump_node_to_str(docp, node, format, (const char *) docp->encoding); + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") xmlSaveNoEmptyTags = old_xml_save_no_empty_tags; + ZEND_DIAGNOSTIC_IGNORED_END } else { int converted_options = XML_SAVE_AS_XML; if (options & XML_SAVE_NO_DECL) { @@ -1655,10 +1663,14 @@ static void dom_document_save_xml(INTERNAL_FUNCTION_PARAMETERS, zend_class_entry } /* Save libxml2 global, override its value, and restore after saving. */ + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") old_xml_save_no_empty_tags = xmlSaveNoEmptyTags; xmlSaveNoEmptyTags = (options & LIBXML_SAVE_NOEMPTYTAG) ? 1 : 0; + ZEND_DIAGNOSTIC_IGNORED_END res = intern->document->handlers->dump_doc_to_str(docp, converted_options, (const char *) docp->encoding); + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") xmlSaveNoEmptyTags = old_xml_save_no_empty_tags; + ZEND_DIAGNOSTIC_IGNORED_END } if (!res) { diff --git a/ext/dom/xml_serializer.c b/ext/dom/xml_serializer.c index a4b46082b0ee5..7684057a391c0 100644 --- a/ext/dom/xml_serializer.c +++ b/ext/dom/xml_serializer.c @@ -1097,7 +1097,10 @@ static int dom_xml_serialize_element_node( /* 14. If ns is the HTML namespace, and the node's list of children is empty, and the node's localName matches * any one of the following void elements: ... */ if (element->children == NULL) { - if (xmlSaveNoEmptyTags) { + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") + int saveNoEmptyTags = xmlSaveNoEmptyTags; + ZEND_DIAGNOSTIC_IGNORED_END + if (saveNoEmptyTags) { /* Do nothing, use the closing style. */ } else if (php_dom_ns_is_fast(element, php_dom_ns_is_html_magic_token)) { size_t name_length = strlen((const char *) element->name); diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index f51e01cdf504e..0105106d9531b 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -813,9 +813,12 @@ static xmlParserInputPtr php_libxml_external_entity_loader(const char *URL, } else { /* make stream not being closed when the zval is freed */ GC_ADDREF(stream->res); + + ZEND_DIAGNOSTIC_IGNORED_START("-Wdeprecated-declarations") pib->context = stream; pib->readcallback = php_libxml_streams_IO_read; pib->closecallback = php_libxml_streams_IO_close; + ZEND_DIAGNOSTIC_IGNORED_END ret = xmlNewIOInputStream(context, pib, enc); if (ret == NULL) { From b8b7add531bbcd00b8fed8522a9e8bae3a59d5e8 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+ndossche@users.noreply.github.com> Date: Tue, 2 Dec 2025 20:59:26 +0100 Subject: [PATCH 10/12] intl: Fix tests for icu update --- ext/intl/tests/msgfmt_format_intlcalendar_variant4.phpt | 2 +- ext/intl/tests/timezone_getDisplayName_variant4.phpt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ext/intl/tests/msgfmt_format_intlcalendar_variant4.phpt b/ext/intl/tests/msgfmt_format_intlcalendar_variant4.phpt index 014bdd4749bca..9436a9e954386 100644 --- a/ext/intl/tests/msgfmt_format_intlcalendar_variant4.phpt +++ b/ext/intl/tests/msgfmt_format_intlcalendar_variant4.phpt @@ -29,4 +29,4 @@ echo "msgf2: ", $msgf->format(array($time, 'date')), " ", ?> --EXPECTF-- Deprecated: Calling IntlGregorianCalendar::__construct() with more than 2 arguments is deprecated, use either IntlGregorianCalendar::createFromDate() or IntlGregorianCalendar::createFromDateTime() instead in %s on line %d -quinta-feira, 17 de maio de 2012 5:35:36 da tarde ptlis +quinta-feira, 17 de maio de 2012 5:35:36 %r(da tarde|p.m.)%r ptlis diff --git a/ext/intl/tests/timezone_getDisplayName_variant4.phpt b/ext/intl/tests/timezone_getDisplayName_variant4.phpt index 39d71f5aa2011..ccde7f8e0ea79 100644 --- a/ext/intl/tests/timezone_getDisplayName_variant4.phpt +++ b/ext/intl/tests/timezone_getDisplayName_variant4.phpt @@ -19,12 +19,12 @@ var_dump($lsb->getDisplayName(false, IntlTimeZone::DISPLAY_SHORT_COMMONLY_USED)) var_dump($lsb->getDisplayName(false, IntlTimeZone::DISPLAY_GENERIC_LOCATION)); ?> ---EXPECT-- -string(3) "GMT" +--EXPECTF-- +string(%d) "%r(GMT|GMT\+0)%r" string(30) "Western European Standard Time" string(13) "Portugal Time" string(21) "Western European Time" string(5) "+0000" -string(3) "GMT" -string(3) "GMT" +string(%d) "%r(GMT|GMT\+00:00)%r" +string(%d) "%r(GMT|GMT\+0)%r" string(13) "Portugal Time" From 631b364117052f13d790b144eac4980eb352d00a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 15 Dec 2025 16:19:32 +0100 Subject: [PATCH 11/12] uri: Update to uriparser-0.9.9-85-g9a31011 (#20707) This is specifically to import uriparser/uriparser#284 to fix CVE-2025-67899. (cherry picked from commit 284e202d2535199fd096c56c699136a0134718da) --- NEWS | 10 +- ext/uri/uriparser/src/UriParse.c | 228 +++++++++++++++---------------- 2 files changed, 117 insertions(+), 121 deletions(-) diff --git a/NEWS b/NEWS index d1ffa9e35f5bd..e6706e997edb9 100644 --- a/NEWS +++ b/NEWS @@ -72,6 +72,12 @@ PHP NEWS via deep structures). (ndossche) . Fixed bug GH-20584 (Information Leak of Memory). (ndossche) +- URI: + . Fixed bug GH-20366 (ext/uri incorrectly throws ValueError when encountering + null byte). (kocsismate) + . Fixed CVE-2025-67899 (uriparser through 0.9.9 allows unbounded recursion + and stack consumption). (Sebastian Pipping) + - XML: . Fixed bug GH-20439 (xml_set_default_handler() does not properly handle special characters in attributes when passing data to callback). (ndossche) @@ -84,10 +90,6 @@ PHP NEWS . Fix assertion failures resulting in crashes with stream filter object parameters. (ndossche) -- URI: - . Fixed bug GH-20366 (ext/uri incorrectly throws ValueError when encountering - null byte). (kocsismate) - 20 Nov 2025, PHP 8.5.0 - Core: diff --git a/ext/uri/uriparser/src/UriParse.c b/ext/uri/uriparser/src/UriParse.c index ed851e94fbd9c..cada02301e00c 100644 --- a/ext/uri/uriparser/src/UriParse.c +++ b/ext/uri/uriparser/src/UriParse.c @@ -81,8 +81,7 @@ static const URI_CHAR * URI_FUNC(ParseAuthority)(URI_TYPE(ParserState) * state, static const URI_CHAR * URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast); -static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, +static const URI_CHAR * URI_FUNC(ParseHexZero)(const URI_CHAR * first, const URI_CHAR * afterLast); static const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * state, const URI_CHAR * first, @@ -92,10 +91,6 @@ static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, - const URI_CHAR * afterLast, - UriMemoryManager * memory); static const URI_CHAR * URI_FUNC(ParseIpLit2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, @@ -116,10 +111,6 @@ static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, - const URI_CHAR * afterLast, - UriMemoryManager * memory); static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, @@ -160,8 +151,7 @@ static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory); -static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, +static const URI_CHAR * URI_FUNC(ParsePort)(const URI_CHAR * first, const URI_CHAR * afterLast); static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, const URI_CHAR * first, @@ -292,8 +282,7 @@ URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * firs switch (*first) { case _UT(':'): { - const URI_CHAR * const afterPort = - URI_FUNC(ParsePort)(state, first + 1, afterLast); + const URI_CHAR * const afterPort = URI_FUNC(ParsePort)(first + 1, afterLast); if (afterPort == NULL) { return NULL; } @@ -311,16 +300,17 @@ URI_FUNC(ParseAuthorityTwo)(URI_TYPE(ParserState) * state, const URI_CHAR * firs * [hexZero]->[HEXDIG][hexZero] * [hexZero]-> */ -static const URI_CHAR * URI_FUNC(ParseHexZero)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, +static const URI_CHAR * URI_FUNC(ParseHexZero)(const URI_CHAR * first, const URI_CHAR * afterLast) { +tail_call: if (first >= afterLast) { return afterLast; } switch (*first) { case URI_SET_HEXDIG(_UT): - return URI_FUNC(ParseHexZero)(state, first + 1, afterLast); + first += 1; + goto tail_call; default: return first; @@ -356,49 +346,37 @@ static URI_INLINE const URI_CHAR * URI_FUNC(ParseHierPart)(URI_TYPE(ParserState) * [ipFutLoop]->[subDelims][ipFutStopGo] * [ipFutLoop]->[unreserved][ipFutStopGo] * [ipFutLoop]-><:>[ipFutStopGo] + * + * [ipFutStopGo]->[ipFutLoop] + * [ipFutStopGo]-> */ static const URI_CHAR * URI_FUNC(ParseIpFutLoop)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } + const URI_CHAR * const originalFirst = first; - switch (*first) { - case _UT(':'): - case URI_SET_SUB_DELIMS(_UT): - case URI_SET_UNRESERVED(_UT): - return URI_FUNC(ParseIpFutStopGo)(state, first + 1, afterLast, memory); + while (first < afterLast) { + switch (*first) { + case _UT(':'): + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): + first += 1; + break; - default: - URI_FUNC(StopSyntax)(state, first, memory); - return NULL; + default: + goto done_looping; + break; + } } -} -/* - * [ipFutStopGo]->[ipFutLoop] - * [ipFutStopGo]-> - */ -static const URI_CHAR * URI_FUNC(ParseIpFutStopGo)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, - const URI_CHAR * afterLast, - UriMemoryManager * memory) { - if (first >= afterLast) { - return afterLast; +done_looping: + if (first == originalFirst) { + URI_FUNC(StopSyntax)(state, first, memory); + return NULL; } - switch (*first) { - case _UT(':'): - case URI_SET_SUB_DELIMS(_UT): - case URI_SET_UNRESERVED(_UT): - return URI_FUNC(ParseIpFutLoop)(state, first, afterLast, memory); - - default: - return first; - } + return first; } /* @@ -430,7 +408,7 @@ static const URI_CHAR * URI_FUNC(ParseIpFuture)(URI_TYPE(ParserState) * state, case URI_SET_HEXDIG(_UT): { const URI_CHAR * afterIpFutLoop; const URI_CHAR * const afterHexZero = - URI_FUNC(ParseHexZero)(state, first + 2, afterLast); + URI_FUNC(ParseHexZero)(first + 2, afterLast); if (afterHexZero == NULL) { return NULL; } @@ -832,6 +810,7 @@ static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { +tail_call: if (first >= afterLast) { if (!URI_FUNC(PushPathSegment)(state, state->uri->scheme.first, first, memory)) { /* SEGMENT BOTH */ @@ -849,14 +828,15 @@ static const URI_CHAR * URI_FUNC(ParseMustBeSegmentNzNc)(URI_TYPE(ParserState) * if (afterPctEncoded == NULL) { return NULL; } - return URI_FUNC(ParseMustBeSegmentNzNc)(state, afterPctEncoded, afterLast, - memory); + first = afterPctEncoded; + goto tail_call; } case _UT('@'): case URI_SET_SUB_DELIMS(_UT): case URI_SET_UNRESERVED(_UT): - return URI_FUNC(ParseMustBeSegmentNzNc)(state, first + 1, afterLast, memory); + first += 1; + goto tail_call; case _UT('/'): { const URI_CHAR * afterZeroMoreSlashSegs; @@ -953,6 +933,7 @@ static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { +tail_call: if (first >= afterLast) { if (!URI_FUNC(OnExitOwnHost2)(state, first, memory)) { URI_FUNC(StopMalloc)(state, memory); @@ -970,7 +951,8 @@ static const URI_CHAR * URI_FUNC(ParseOwnHost2)(URI_TYPE(ParserState) * state, if (afterPctSubUnres == NULL) { return NULL; } - return URI_FUNC(ParseOwnHost2)(state, afterPctSubUnres, afterLast, memory); + first = afterPctSubUnres; + goto tail_call; } default: @@ -1006,74 +988,69 @@ static URI_INLINE UriBool URI_FUNC(OnExitOwnHostUserInfo)(URI_TYPE(ParserState) return URI_TRUE; /* Success */ } -/* - * [ownHostUserInfo]->[ownHostUserInfoNz] - * [ownHostUserInfo]-> - */ -static URI_INLINE const URI_CHAR * -URI_FUNC(ParseOwnHostUserInfo)(URI_TYPE(ParserState) * state, const URI_CHAR * first, - const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first, memory)) { - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return afterLast; - } - - switch (*first) { - case URI_SET_PCHAR(_UT): - return URI_FUNC(ParseOwnHostUserInfoNz)(state, first, afterLast, memory); - - default: - if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first, memory)) { - URI_FUNC(StopMalloc)(state, memory); - return NULL; - } - return first; - } -} - /* * [ownHostUserInfoNz]->[pctSubUnres][ownHostUserInfo] * [ownHostUserInfoNz]-><:>[ownPortUserInfo] * [ownHostUserInfoNz]-><@>[ownHost] + * + * [ownHostUserInfo]->[ownHostUserInfoNz] + * [ownHostUserInfo]-> */ static const URI_CHAR * URI_FUNC(ParseOwnHostUserInfoNz)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { - if (first >= afterLast) { - URI_FUNC(StopSyntax)(state, afterLast, memory); - return NULL; - } + const URI_CHAR * const originalFirst = first; + + while (first < afterLast) { + switch (*first) { + case _UT('%'): + case URI_SET_SUB_DELIMS(_UT): + case URI_SET_UNRESERVED(_UT): { + const URI_CHAR * const afterPctSubUnres = + URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory); + if (afterPctSubUnres == NULL) { + return NULL; + } + first = afterPctSubUnres; + break; + } - switch (*first) { - case _UT('%'): - case URI_SET_SUB_DELIMS(_UT): - case URI_SET_UNRESERVED(_UT): { - const URI_CHAR * const afterPctSubUnres = - URI_FUNC(ParsePctSubUnres)(state, first, afterLast, memory); - if (afterPctSubUnres == NULL) { - return NULL; + default: + goto done_looping; + break; } - return URI_FUNC(ParseOwnHostUserInfo)(state, afterPctSubUnres, afterLast, memory); } - case _UT(':'): - state->uri->hostText.afterLast = first; /* HOST END */ - state->uri->portText.first = first + 1; /* PORT BEGIN */ - return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast, memory); +done_looping: + if (first < afterLast) { + switch (*first) { + case _UT(':'): + state->uri->hostText.afterLast = first; /* HOST END */ + state->uri->portText.first = first + 1; /* PORT BEGIN */ + return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast, memory); - case _UT('@'): - state->uri->userInfo.afterLast = first; /* USERINFO END */ - state->uri->hostText.first = first + 1; /* HOST BEGIN */ - return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast, memory); + case _UT('@'): + state->uri->userInfo.afterLast = first; /* USERINFO END */ + state->uri->hostText.first = first + 1; /* HOST BEGIN */ + return URI_FUNC(ParseOwnHost)(state, first + 1, afterLast, memory); - default: - URI_FUNC(StopSyntax)(state, first, memory); + default: + break; + } + } + + if (first == originalFirst) { + URI_FUNC(StopSyntax)(state, afterLast, memory); return NULL; } + + if (!URI_FUNC(OnExitOwnHostUserInfo)(state, first, memory)) { + URI_FUNC(StopMalloc)(state, memory); + return NULL; + } + + return first; } static URI_INLINE UriBool URI_FUNC(OnExitOwnPortUserInfo)(URI_TYPE(ParserState) * state, @@ -1117,6 +1094,7 @@ static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * s const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { +tail_call: if (first >= afterLast) { if (!URI_FUNC(OnExitOwnPortUserInfo)(state, first, memory)) { URI_FUNC(StopMalloc)(state, memory); @@ -1140,7 +1118,8 @@ static const URI_CHAR * URI_FUNC(ParseOwnPortUserInfo)(URI_TYPE(ParserState) * s return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast, memory); case URI_SET_DIGIT(_UT): - return URI_FUNC(ParseOwnPortUserInfo)(state, first + 1, afterLast, memory); + first += 1; + goto tail_call; case _UT('%'): state->uri->portText.first = NULL; /* Not a port, reset */ @@ -1176,6 +1155,7 @@ static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { +tail_call: if (first >= afterLast) { URI_FUNC(StopSyntax)(state, afterLast, memory); return NULL; @@ -1190,11 +1170,13 @@ static const URI_CHAR * URI_FUNC(ParseOwnUserInfo)(URI_TYPE(ParserState) * state if (afterPctSubUnres == NULL) { return NULL; } - return URI_FUNC(ParseOwnUserInfo)(state, afterPctSubUnres, afterLast, memory); + first = afterPctSubUnres; + goto tail_call; } case _UT(':'): - return URI_FUNC(ParseOwnUserInfo)(state, first + 1, afterLast, memory); + first += 1; + goto tail_call; case _UT('@'): /* SURE */ @@ -1254,6 +1236,7 @@ static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * stat const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { +tail_call: if (first >= afterLast) { return afterLast; } @@ -1270,7 +1253,8 @@ static const URI_CHAR * URI_FUNC(ParsePathAbsEmpty)(URI_TYPE(ParserState) * stat URI_FUNC(StopMalloc)(state, memory); return NULL; } - return URI_FUNC(ParsePathAbsEmpty)(state, afterSegment, afterLast, memory); + first = afterSegment; + goto tail_call; } default: @@ -1443,16 +1427,17 @@ static const URI_CHAR * URI_FUNC(ParsePctSubUnres)(URI_TYPE(ParserState) * state * [port]->[DIGIT][port] * [port]-> */ -static const URI_CHAR * URI_FUNC(ParsePort)(URI_TYPE(ParserState) * state, - const URI_CHAR * first, +static const URI_CHAR * URI_FUNC(ParsePort)(const URI_CHAR * first, const URI_CHAR * afterLast) { +tail_call: if (first >= afterLast) { return afterLast; } switch (*first) { case URI_SET_DIGIT(_UT): - return URI_FUNC(ParsePort)(state, first + 1, afterLast); + first += 1; + goto tail_call; default: return first; @@ -1469,6 +1454,7 @@ static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { +tail_call: if (first >= afterLast) { return afterLast; } @@ -1480,12 +1466,14 @@ static const URI_CHAR * URI_FUNC(ParseQueryFrag)(URI_TYPE(ParserState) * state, if (afterPchar == NULL) { return NULL; } - return URI_FUNC(ParseQueryFrag)(state, afterPchar, afterLast, memory); + first = afterPchar; + goto tail_call; } case _UT('/'): case _UT('?'): - return URI_FUNC(ParseQueryFrag)(state, first + 1, afterLast, memory); + first += 1; + goto tail_call; default: return first; @@ -1500,6 +1488,7 @@ static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { +tail_call: if (first >= afterLast) { return afterLast; } @@ -1511,7 +1500,8 @@ static const URI_CHAR * URI_FUNC(ParseSegment)(URI_TYPE(ParserState) * state, if (afterPchar == NULL) { return NULL; } - return URI_FUNC(ParseSegment)(state, afterPchar, afterLast, memory); + first = afterPchar; + goto tail_call; } default: @@ -1572,6 +1562,7 @@ static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { +tail_call: if (first >= afterLast) { if (!URI_FUNC(OnExitSegmentNzNcOrScheme2)(state, first, memory)) { URI_FUNC(StopMalloc)(state, memory); @@ -1586,7 +1577,8 @@ static const URI_CHAR * URI_FUNC(ParseSegmentNzNcOrScheme2)(URI_TYPE(ParserState case _UT('-'): case URI_SET_ALPHA(_UT): case URI_SET_DIGIT(_UT): - return URI_FUNC(ParseSegmentNzNcOrScheme2)(state, first + 1, afterLast, memory); + first += 1; + goto tail_call; case _UT('%'): { const URI_CHAR * const afterPctEncoded = @@ -1796,6 +1788,7 @@ static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * const URI_CHAR * first, const URI_CHAR * afterLast, UriMemoryManager * memory) { +tail_call: if (first >= afterLast) { return afterLast; } @@ -1812,7 +1805,8 @@ static const URI_CHAR * URI_FUNC(ParseZeroMoreSlashSegs)(URI_TYPE(ParserState) * URI_FUNC(StopMalloc)(state, memory); return NULL; } - return URI_FUNC(ParseZeroMoreSlashSegs)(state, afterSegment, afterLast, memory); + first = afterSegment; + goto tail_call; } default: From 346fc95827fdda478cf881935d25593ed1d75dda Mon Sep 17 00:00:00 2001 From: Volker Dusch Date: Tue, 16 Dec 2025 16:30:45 +0100 Subject: [PATCH 12/12] Update NEWS --- NEWS | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index e6706e997edb9..c20ddee517b1b 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -?? ??? ????, PHP 8.5.1 +18 Dec 2025, PHP 8.5.1 - Core: . Sync all boost.context files with release 1.86.0. (mvorisek) @@ -51,6 +51,8 @@ PHP NEWS - PDO: . Fixed bug GH-20553 (PDO::FETCH_CLASSTYPE ignores $constructorArgs in PHP 8.5.0). (Girgias) + . Fixed GHSA-8xr5-qppj-gvwj (PDO quoting result null deref). (CVE-2025-14180) + (Jakub Zelenka) - Phar: . Fixed bug GH-20442 (Phar does not respect case-insensitiveness of @@ -70,7 +72,12 @@ PHP NEWS . Fix memory leak in array_diff() with custom type checks. (ndossche) . Fixed bug GH-20583 (Stack overflow in http_build_query via deep structures). (ndossche) - . Fixed bug GH-20584 (Information Leak of Memory). (ndossche) + . Fixed GHSA-www2-q4fc-65wf (Null byte termination in dns_get_record()). + (ndossche) + . Fixed GHSA-h96m-rvf9-jgm2 (Heap buffer overflow in array_merge()). + (CVE-2025-14178) (ndossche) + . Fixed GHSA-3237-qqm7-mfv7 (Information Leak of Memory in getimagesize). + (CVE-2025-14177) (ndossche) - URI: . Fixed bug GH-20366 (ext/uri incorrectly throws ValueError when encountering