diff --git a/NEWS b/NEWS index c05b203a8d8..548349b4063 100644 --- a/NEWS +++ b/NEWS @@ -59,6 +59,8 @@ PHP NEWS conditions. (timwolla) . Further clean up the internal API. (timwolla) . Fixed bug GH-19892 (Refcounting on zend_empty_array). (ilutov, timwolla) + . Fixed handling of port numbers > 65535 with the internal + `php_uri_parse_to_struct()` API. (timwolla) - Windows: . Fix GH-19722 (_get_osfhandle asserts in debug mode when given a socket). diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c index c747020ad62..b36d232de95 100644 --- a/ext/standard/ftp_fopen_wrapper.c +++ b/ext/standard/ftp_fopen_wrapper.c @@ -155,7 +155,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char if (resource->port == 0) resource->port = 21; - transport_len = (int)spprintf(&transport, 0, "tcp://%s:%d", ZSTR_VAL(resource->host), resource->port); + transport_len = (int)spprintf(&transport, 0, "tcp://%s:" ZEND_LONG_FMT, ZSTR_VAL(resource->host), resource->port); stream = php_stream_xport_create(transport, transport_len, REPORT_ERRORS, STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT, NULL, NULL, context, NULL, NULL); efree(transport); if (stream == NULL) { diff --git a/ext/standard/http_fopen_wrapper.c b/ext/standard/http_fopen_wrapper.c index b8ede088517..e342c776666 100644 --- a/ext/standard/http_fopen_wrapper.c +++ b/ext/standard/http_fopen_wrapper.c @@ -446,7 +446,7 @@ static php_stream *php_stream_url_wrap_http_ex(php_stream_wrapper *wrapper, use_proxy = 1; transport_string = zend_string_copy(Z_STR_P(tmpzval)); } else { - transport_string = zend_strpprintf(0, "%s://%s:%d", use_ssl ? "ssl" : "tcp", ZSTR_VAL(resource->host), resource->port); + transport_string = zend_strpprintf(0, "%s://%s:" ZEND_LONG_FMT, use_ssl ? "ssl" : "tcp", ZSTR_VAL(resource->host), resource->port); } } @@ -1083,7 +1083,7 @@ finish: header_info.location = NULL; } if ((use_ssl && resource->port != 443) || (!use_ssl && resource->port != 80)) { - spprintf(&new_path, 0, "%s://%s:%d%s", ZSTR_VAL(resource->scheme), + spprintf(&new_path, 0, "%s://%s:" ZEND_LONG_FMT "%s", ZSTR_VAL(resource->scheme), ZSTR_VAL(resource->host), resource->port, loc_path); } else { spprintf(&new_path, 0, "%s://%s%s", ZSTR_VAL(resource->scheme), diff --git a/ext/uri/php_uri.h b/ext/uri/php_uri.h index dd796433f09..9cfe6dce1ab 100644 --- a/ext/uri/php_uri.h +++ b/ext/uri/php_uri.h @@ -27,7 +27,9 @@ typedef struct php_uri { zend_string *user; zend_string *password; zend_string *host; - unsigned short port; + /* port is a zend_long to match the userland port getter, which + * returns the port in zval. */ + zend_long port; zend_string *path; zend_string *query; zend_string *fragment; diff --git a/ext/uri/tests/100.phpt b/ext/uri/tests/100.phpt index bf3d34c2925..0c1abcdd00b 100644 --- a/ext/uri/tests/100.phpt +++ b/ext/uri/tests/100.phpt @@ -10,7 +10,7 @@ var_dump(zend_test_uri_parser("https://%65xample:%65xample@%65xample.com:123/%65 ?> --EXPECT-- -array(2) { +array(3) { ["normalized"]=> array(8) { ["scheme"]=> @@ -49,4 +49,23 @@ array(2) { ["fragment"]=> string(9) "%65xample" } + ["struct"]=> + array(8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + string(9) "%65xample" + ["password"]=> + string(9) "%65xample" + ["host"]=> + string(13) "%65xample.com" + ["port"]=> + int(123) + ["path"]=> + string(15) "/%65xample.html" + ["query"]=> + string(19) "%65xample=%65xample" + ["fragment"]=> + string(9) "%65xample" + } } diff --git a/ext/uri/tests/102.phpt b/ext/uri/tests/102.phpt new file mode 100644 index 00000000000..6080c1be884 --- /dev/null +++ b/ext/uri/tests/102.phpt @@ -0,0 +1,71 @@ +--TEST-- +Test the handling large ports for the uri struct +--EXTENSIONS-- +uri +zend_test +--FILE-- + +--EXPECT-- +array(3) { + ["normalized"]=> + array(8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + int(42424242) + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL + } + ["raw"]=> + array(8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + int(42424242) + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL + } + ["struct"]=> + array(8) { + ["scheme"]=> + string(5) "https" + ["username"]=> + NULL + ["password"]=> + NULL + ["host"]=> + string(11) "example.com" + ["port"]=> + int(42424242) + ["path"]=> + string(0) "" + ["query"]=> + NULL + ["fragment"]=> + NULL + } +} diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 99bdae0bcc7..6b0139e186b 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -746,6 +746,11 @@ static ZEND_FUNCTION(zend_test_uri_parser) RETURN_THROWS(); } + php_uri *uri_struct = php_uri_parse_to_struct(parser, ZSTR_VAL(uri_string), ZSTR_LEN(uri_string), PHP_URI_COMPONENT_READ_MODE_RAW, false); + if (uri_struct == NULL) { + RETURN_THROWS(); + } + zval value; array_init(return_value); @@ -787,7 +792,56 @@ static ZEND_FUNCTION(zend_test_uri_parser) php_uri_get_fragment(uri, PHP_URI_COMPONENT_READ_MODE_RAW, &value); zend_hash_add(Z_ARR(raw), ZSTR_KNOWN(ZEND_STR_FRAGMENT), &value); zend_hash_str_add(Z_ARR_P(return_value), "raw", strlen("raw"), &raw); + zval from_struct; + zval dummy; + array_init(&from_struct); + if (uri_struct->scheme) { + ZVAL_STR_COPY(&dummy, uri_struct->scheme); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_SCHEME), &dummy); + if (uri_struct->user) { + ZVAL_STR_COPY(&dummy, uri_struct->user); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_USERNAME), &dummy); + if (uri_struct->password) { + ZVAL_STR_COPY(&dummy, uri_struct->password); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_PASSWORD), &dummy); + if (uri_struct->host) { + ZVAL_STR_COPY(&dummy, uri_struct->host); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_HOST), &dummy); + ZVAL_LONG(&dummy, uri_struct->port); + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_PORT), &dummy); + if (uri_struct->path) { + ZVAL_STR_COPY(&dummy, uri_struct->path); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_PATH), &dummy); + if (uri_struct->query) { + ZVAL_STR_COPY(&dummy, uri_struct->query); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_QUERY), &dummy); + if (uri_struct->fragment) { + ZVAL_STR_COPY(&dummy, uri_struct->fragment); + } else { + ZVAL_NULL(&dummy); + } + zend_hash_add(Z_ARR(from_struct), ZSTR_KNOWN(ZEND_STR_FRAGMENT), &dummy); + zend_hash_str_add(Z_ARR_P(return_value), "struct", strlen("struct"), &from_struct); + php_uri_struct_free(uri_struct); php_uri_free(uri); }