diff --git a/NEWS b/NEWS index 23bb612c482ca..dc91f999fb15e 100644 --- a/NEWS +++ b/NEWS @@ -110,6 +110,8 @@ PHP NEWS . pg_connect checks if connection_string contains any null byte, pg_close_stmt check if the statement contains any null byte. (David Carlier) + . Added pg_service to get the connection current service identifier. + (David Carlier) - POSIX: . Added POSIX_SC_OPEN_MAX constant to get the number of file descriptors diff --git a/UPGRADING b/UPGRADING index 7488912c88804..1a525f22f4411 100644 --- a/UPGRADING +++ b/UPGRADING @@ -273,6 +273,7 @@ PHP 8.5 UPGRADE NOTES . pg_close_stmt offers an alternative way to close a prepared statement from the DEALLOCATE sql command in that we can reuse its name afterwards. + . pg_service returns the ongoing service name of the connection. - Reflection: . ReflectionConstant::getFileName() was introduced. diff --git a/ext/pgsql/config.m4 b/ext/pgsql/config.m4 index 48fbbae34ace0..1409f879b52cc 100644 --- a/ext/pgsql/config.m4 +++ b/ext/pgsql/config.m4 @@ -31,6 +31,9 @@ if test "$PHP_PGSQL" != "no"; then PHP_CHECK_LIBRARY([pq], [PQclosePrepared], [AC_DEFINE([HAVE_PG_CLOSE_STMT], [1], [PostgreSQL 17 or later])],, [$PGSQL_LIBS]) + PHP_CHECK_LIBRARY([pq], [PQservice], + [AC_DEFINE([HAVE_PG_SERVICE], [1], [PostgreSQL 18 or later])],, + [$PGSQL_LIBS]) old_CFLAGS=$CFLAGS CFLAGS="$CFLAGS $PGSQL_CFLAGS" diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 3f16c2e88f2fa..c53bf8ed9a35c 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -907,6 +907,7 @@ PHP_FUNCTION(pg_close) #define PHP_PG_HOST 6 #define PHP_PG_VERSION 7 #define PHP_PG_JIT 8 +#define PHP_PG_SERVICE 9 /* php_pgsql_get_link_info */ static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type) @@ -991,6 +992,12 @@ static void php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type PQclear(res); return; } +#if defined(HAVE_PG_SERVICE) + case PHP_PG_SERVICE: { + result = PQservice(pgsql); + break; + } +#endif EMPTY_SWITCH_DEFAULT_CASE() } if (result) { @@ -1047,6 +1054,13 @@ PHP_FUNCTION(pg_jit) php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_JIT); } +#if defined(HAVE_PG_SERVICE) +PHP_FUNCTION(pg_service) +{ + php_pgsql_get_link_info(INTERNAL_FUNCTION_PARAM_PASSTHRU,PHP_PG_SERVICE); +} +#endif + /* Returns the value of a server parameter */ PHP_FUNCTION(pg_parameter_status) { diff --git a/ext/pgsql/pgsql.stub.php b/ext/pgsql/pgsql.stub.php index cac22e3a30301..04e648eff8d50 100644 --- a/ext/pgsql/pgsql.stub.php +++ b/ext/pgsql/pgsql.stub.php @@ -508,6 +508,9 @@ function pg_version(?PgSql\Connection $connection = null): array {} */ function pg_jit(?PgSql\Connection $connection = null): array {} +#ifdef HAVE_PG_SERVICE + function pg_service(?PgSql\Connection $connection = null): string {} +#endif /** * @param PgSql\Connection|string $connection * @refcount 1 diff --git a/ext/pgsql/pgsql_arginfo.h b/ext/pgsql/pgsql_arginfo.h index 336dd7ff86d04..cb58645e5e9f5 100644 --- a/ext/pgsql/pgsql_arginfo.h +++ b/ext/pgsql/pgsql_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 49e3493be11a5da1ed9a57339f14f92f34bf5d1b */ + * Stub hash: 3cf44ca06d11cad086829d3d04900ade3cacb88b */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_pg_connect, 0, 1, PgSql\\Connection, MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, connection_string, IS_STRING, 0) @@ -38,6 +38,12 @@ ZEND_END_ARG_INFO() #define arginfo_pg_jit arginfo_pg_version +#if defined(HAVE_PG_SERVICE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pg_service, 0, 0, IS_STRING, 0) + ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, connection, PgSql\\Connection, 1, "null") +ZEND_END_ARG_INFO() +#endif + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pg_parameter_status, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_INFO(0, connection) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) @@ -514,6 +520,9 @@ ZEND_FUNCTION(pg_tty); ZEND_FUNCTION(pg_host); ZEND_FUNCTION(pg_version); ZEND_FUNCTION(pg_jit); +#if defined(HAVE_PG_SERVICE) +ZEND_FUNCTION(pg_service); +#endif ZEND_FUNCTION(pg_parameter_status); ZEND_FUNCTION(pg_ping); ZEND_FUNCTION(pg_query); @@ -623,6 +632,9 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(pg_host, arginfo_pg_host) ZEND_FE(pg_version, arginfo_pg_version) ZEND_FE(pg_jit, arginfo_pg_jit) +#if defined(HAVE_PG_SERVICE) + ZEND_FE(pg_service, arginfo_pg_service) +#endif ZEND_FE(pg_parameter_status, arginfo_pg_parameter_status) ZEND_FE(pg_ping, arginfo_pg_ping) ZEND_FE(pg_query, arginfo_pg_query) diff --git a/ext/pgsql/tests/pg_service.phpt b/ext/pgsql/tests/pg_service.phpt new file mode 100644 index 0000000000000..0ce1be7285ebc --- /dev/null +++ b/ext/pgsql/tests/pg_service.phpt @@ -0,0 +1,19 @@ +--TEST-- +PostgreSQL connection service field support +--EXTENSIONS-- +pgsql +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +string(%d) "%A" diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index b187949699087..99e6983b0ffc0 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -733,22 +733,29 @@ PHP_METHOD(SplFixedArray, fromArray) zend_ulong num_index, max_index = 0; zend_long tmp; - ZEND_HASH_FOREACH_KEY(Z_ARRVAL_P(data), num_index, str_index) { - if (str_index != NULL || (zend_long)num_index < 0) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "array must contain only positive integer keys"); + if (HT_IS_PACKED(Z_ARRVAL_P(data))) { + /* If there are no holes, then nNumUsed is the number of elements. + * If there are holes, then nNumUsed is the index of the last element. */ + tmp = Z_ARRVAL_P(data)->nNumUsed; + } else { + ZEND_HASH_MAP_FOREACH_KEY(Z_ARRVAL_P(data), num_index, str_index) { + if (str_index != NULL || (zend_long)num_index < 0) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "array must contain only positive integer keys"); + RETURN_THROWS(); + } + + if (num_index > max_index) { + max_index = num_index; + } + } ZEND_HASH_FOREACH_END(); + + tmp = max_index + 1; + if (tmp <= 0) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "integer overflow detected"); RETURN_THROWS(); } - - if (num_index > max_index) { - max_index = num_index; - } - } ZEND_HASH_FOREACH_END(); - - tmp = max_index + 1; - if (tmp <= 0) { - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "integer overflow detected"); - RETURN_THROWS(); } + spl_fixedarray_init(&array, tmp); ZEND_HASH_FOREACH_NUM_KEY_VAL(Z_ARRVAL_P(data), num_index, element) { diff --git a/ext/standard/file.h b/ext/standard/file.h index 3a9cf1435b143..f8faebd028293 100644 --- a/ext/standard/file.h +++ b/ext/standard/file.h @@ -36,7 +36,6 @@ PHPAPI PHP_FUNCTION(fpassthru); PHP_MINIT_FUNCTION(user_streams); -PHPAPI int php_le_stream_context(void); PHPAPI zend_result php_copy_file(const char *src, const char *dest); PHPAPI zend_result php_copy_file_ex(const char *src, const char *dest, int src_flags); PHPAPI zend_result php_copy_file_ctx(const char *src, const char *dest, int src_flags, php_stream_context *ctx); diff --git a/main/php_streams.h b/main/php_streams.h index f534bc27285f1..02281c3913fcd 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -285,6 +285,10 @@ END_EXTERN_C() #define php_stream_from_res_no_verify(xstr, pzval) (xstr) = (php_stream*)zend_fetch_resource2((res), "stream", php_file_le_stream(), php_file_le_pstream()) #define php_stream_from_zval_no_verify(xstr, pzval) (xstr) = (php_stream*)zend_fetch_resource2_ex((pzval), "stream", php_file_le_stream(), php_file_le_pstream()) +static zend_always_inline php_stream* php_stream_from_zval_no_verify_no_error(zval *zval) { + return (php_stream*)zend_fetch_resource2_ex(zval, NULL, php_file_le_stream(), php_file_le_pstream()); +} + BEGIN_EXTERN_C() static zend_always_inline bool php_stream_zend_parse_arg_into_stream( diff --git a/main/streams/php_stream_context.h b/main/streams/php_stream_context.h index d4ebe29bc162e..a5325a94642c9 100644 --- a/main/streams/php_stream_context.h +++ b/main/streams/php_stream_context.h @@ -25,14 +25,17 @@ typedef void (*php_stream_notification_func)(php_stream_context *context, #define PHP_STREAM_NOTIFIER_PROGRESS 1 +/* TODO: Remove dependence on ext/standard/file.h for the default context global */ +#define php_stream_context_get_default(without_context) \ + (without_context) ? NULL : FG(default_context) ? FG(default_context) : \ + (FG(default_context) = php_stream_context_alloc()) + /* Attempt to fetch context from the zval passed, If no context was passed, use the default context The default context has not yet been created, do it now. */ #define php_stream_context_from_zval(zcontext, nocontext) ( \ (zcontext) ? zend_fetch_resource_ex(zcontext, "Stream-Context", php_le_stream_context()) : \ - (nocontext) ? NULL : \ - FG(default_context) ? FG(default_context) : \ - (FG(default_context) = php_stream_context_alloc()) ) + php_stream_context_get_default(nocontext)) #define php_stream_context_to_zval(context, zval) { ZVAL_RES(zval, (context)->res); GC_ADDREF((context)->res); } @@ -53,6 +56,7 @@ struct _php_stream_context { }; BEGIN_EXTERN_C() +PHPAPI int php_le_stream_context(void); PHPAPI void php_stream_context_free(php_stream_context *context); PHPAPI php_stream_context *php_stream_context_alloc(void); PHPAPI zval *php_stream_context_get_option(php_stream_context *context,