diff --git a/NEWS b/NEWS index 74816c94a2906..86a2174a986f9 100644 --- a/NEWS +++ b/NEWS @@ -86,6 +86,8 @@ PHP NEWS transmitted data can remain unacknowledged. (James Lucas) . Added AF_UNSPEC support for sock_addrinfo_lookup() as a sole umbrella for AF_INET* family only. (David Carlier) + . Fixed GH-20532 (socket_addrinfo_lookup gives the error code with a new optional + parameter). (David Carlier) - SPL: . DirectoryIterator key can now work better with filesystem supporting larger diff --git a/UPGRADING b/UPGRADING index 3d0a56756cdcc..0d24268b787a9 100644 --- a/UPGRADING +++ b/UPGRADING @@ -77,6 +77,11 @@ PHP 8.6 UPGRADE NOTES - Phar: . Phar::mungServer() now supports reference values. +- Sockets: + . socket_addrinfo_lookup() now has an additional optional argument $error + when not null, and on failure, gives the error code (one of the EAI_* + constants). + - Zip: . ZipArchive::extractTo now raises a TypeError for the files argument if one or more of the entries is not @@ -105,6 +110,9 @@ PHP 8.6 UPGRADE NOTES - Hash: . The bundled version of xxHash was upgraded to 0.8.2. +- mysqli + . Added new constant MYSQLI_OPT_COMPRESS. + ======================================== 10. New Global Constants ======================================== @@ -112,6 +120,23 @@ PHP 8.6 UPGRADE NOTES - Sockets: . TCP_USER_TIMEOUT (Linux only). . AF_UNSPEC. + . EAI_BADFLAGS. + . EAI_NONAME. + . EAI_AGAIN. + . EAI_FAIL. + . EAI_NODATA. + . EAI_FAMILY. + . EAI_SOCKTYPE. + . EAI_SERVICE. + . EAI_ADDRFAMILY. + . EAI_SYSTEM. + . EAI_OVERFLOW + . EAI_INPROGRESS. + . EAI_CANCELED. + . EAI_NOTCANCELED. + . EAI_ALLDONE. + . EAI_INTR. + . EAI_IDN_ENCODE. ======================================== 11. Changes to INI File Handling diff --git a/ext/mysqli/mysqli.stub.php b/ext/mysqli/mysqli.stub.php index 370da77e62a25..7ca2a20ca1b77 100644 --- a/ext/mysqli/mysqli.stub.php +++ b/ext/mysqli/mysqli.stub.php @@ -58,6 +58,11 @@ * @cvalue MYSQL_OPT_SSL_VERIFY_SERVER_CERT */ const MYSQLI_OPT_SSL_VERIFY_SERVER_CERT = UNKNOWN; +/** + * @var int + * @cvalue MYSQL_OPT_COMPRESS + */ +const MYSQLI_OPT_COMPRESS = UNKNOWN; /** * @var int diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index 789464a762538..717af442d84fc 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: fecde55745fb219cb15fd35a54a71371ef2b8b7d */ + * Stub hash: c0af8c627a063fbd2c8b76c63b5e70c8ddd1e4f9 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING) ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0) @@ -1045,6 +1045,7 @@ static void register_mysqli_symbols(int module_number) REGISTER_LONG_CONSTANT("MYSQLI_OPT_NET_READ_BUFFER_SIZE", MYSQLND_OPT_NET_READ_BUFFER_SIZE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLI_OPT_INT_AND_FLOAT_NATIVE", MYSQLND_OPT_INT_AND_FLOAT_NATIVE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLI_OPT_SSL_VERIFY_SERVER_CERT", MYSQL_OPT_SSL_VERIFY_SERVER_CERT, CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("MYSQLI_OPT_COMPRESS", MYSQL_OPT_COMPRESS, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLI_SERVER_PUBLIC_KEY", MYSQL_SERVER_PUBLIC_KEY, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_SSL", CLIENT_SSL, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MYSQLI_CLIENT_COMPRESS", CLIENT_COMPRESS, CONST_PERSISTENT); diff --git a/ext/mysqli/tests/mysqli_constants.phpt b/ext/mysqli/tests/mysqli_constants.phpt index 982fe47f75cef..0b5fa977ac1dc 100644 --- a/ext/mysqli/tests/mysqli_constants.phpt +++ b/ext/mysqli/tests/mysqli_constants.phpt @@ -47,6 +47,7 @@ $expected_constants = array( "MYSQLI_SERVER_QUERY_NO_GOOD_INDEX_USED"=> true, "MYSQLI_SERVER_QUERY_NO_INDEX_USED" => true, "MYSQLI_OPT_LOAD_DATA_LOCAL_DIR" => true, + "MYSQLI_OPT_COMPRESS" => true, "MYSQLI_IS_MARIADB" => true, "MYSQLI_TYPE_DECIMAL" => true, diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 1c5cab899e783..ace1206682042 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -17199,6 +17199,7 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op2.var), IS_UNKNOWN, 1); } break; + case ZEND_FE_RESET_RW: case ZEND_BIND_INIT_STATIC_OR_JMP: if (opline->op1_type == IS_CV) { old_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->op1.var)); @@ -17223,6 +17224,7 @@ static int zend_jit_trace_handler(zend_jit_ctx *jit, const zend_op_array *op_arr SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->op2.var), old_info); } break; + case ZEND_FE_RESET_RW: case ZEND_BIND_INIT_STATIC_OR_JMP: if (opline->op1_type == IS_CV) { SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->op1.var), old_info); diff --git a/ext/opcache/tests/jit/gh20818.phpt b/ext/opcache/tests/jit/gh20818.phpt new file mode 100644 index 0000000000000..9423856b66bec --- /dev/null +++ b/ext/opcache/tests/jit/gh20818.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-20818 (Segfault in Tracing JIT with Object Reference) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.jit=tracing +opcache.jit_buffer_size=1M +--FILE-- + 1], + (object) ["" => 1], + (object) [], +]; + +for ($i = 0; $i < 200; $i += 1) { + foreach ($data as $entry) { + process($entry); + } +} + +echo "Done\n"; +?> +--EXPECT-- +Done diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index 54f862d55366f..accaf4bbbcfdc 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -2751,16 +2751,18 @@ PHP_FUNCTION(socket_addrinfo_lookup) { zend_string *service = NULL; zend_string *hostname, *key; - zval *hint, *zhints = NULL; + zval *hint, *zhints = NULL, *error_code = NULL; + int ret = 0; struct addrinfo hints, *result, *rp; php_addrinfo *res; - ZEND_PARSE_PARAMETERS_START(1, 3) + ZEND_PARSE_PARAMETERS_START(1, 4) Z_PARAM_STR(hostname) Z_PARAM_OPTIONAL Z_PARAM_STR_OR_NULL(service) Z_PARAM_ARRAY(zhints) + Z_PARAM_ZVAL_OR_NULL(error_code) ZEND_PARSE_PARAMETERS_END(); memset(&hints, 0, sizeof(hints)); @@ -2848,7 +2850,10 @@ PHP_FUNCTION(socket_addrinfo_lookup) } ZEND_HASH_FOREACH_END(); } - if (getaddrinfo(ZSTR_VAL(hostname), service ? ZSTR_VAL(service) : NULL, &hints, &result) != 0) { + if ((ret = getaddrinfo(ZSTR_VAL(hostname), service ? ZSTR_VAL(service) : NULL, &hints, &result)) != 0) { + if (error_code) { + ZEND_TRY_ASSIGN_REF_LONG(error_code, ret); + } RETURN_FALSE; } diff --git a/ext/sockets/sockets.stub.php b/ext/sockets/sockets.stub.php index 0f645da25ce59..56b2ac07e868f 100644 --- a/ext/sockets/sockets.stub.php +++ b/ext/sockets/sockets.stub.php @@ -2067,6 +2067,136 @@ const SHUT_RDWR = UNKNOWN; #endif + +#ifdef EAI_BADFLAGS +/** + * @var int + * @cvalue EAI_BADFLAGS + */ +const EAI_BADFLAGS = UNKNOWN; +#endif +#ifdef EAI_NONAME +/** + * @var int + * @cvalue EAI_NONAME + */ +const EAI_NONAME = UNKNOWN; +#endif +#ifdef EAI_AGAIN +/** + * @var int + * @cvalue EAI_AGAIN + */ +const EAI_AGAIN = UNKNOWN; +#endif +#ifdef EAI_FAIL +/** + * @var int + * @cvalue EAI_FAIL + */ +const EAI_FAIL = UNKNOWN; +#endif +#ifdef EAI_NODATA +/** + * @var int + * @cvalue EAI_NODATA + */ +const EAI_NODATA = UNKNOWN; +#endif +#ifdef EAI_FAMILY +/** + * @var int + * @cvalue EAI_FAMILY + */ +const EAI_FAMILY = UNKNOWN; +#endif +#ifdef EAI_SOCKTYPE +/** + * @var int + * @cvalue EAI_SOCKTYPE + */ +const EAI_SOCKTYPE = UNKNOWN; +#endif +#ifdef EAI_SERVICE +/** + * @var int + * @cvalue EAI_SERVICE + */ +const EAI_SERVICE = UNKNOWN; +#endif +#ifdef EAI_ADDRFAMILY +/** + * @var int + * @cvalue EAI_ADDRFAMILY + */ +const EAI_ADDRFAMILY = UNKNOWN; +#else +#ifdef EAI_FAMILY +/** + * @var int + * @cvalue EAI_FAMILY + */ +const EAI_ADDRFAMILY = UNKNOWN; +#else +#endif +#endif +#ifdef EAI_SYSTEM +/** + * @var int + * @cvalue EAI_SYSTEM + */ +const EAI_SYSTEM = UNKNOWN; +#endif +#ifdef EAI_OVERFLOW +/** + * @var int + * @cvalue EAI_OVERFLOW + */ +const EAI_OVERFLOW = UNKNOWN; +#endif +#ifdef EAI_INPROGRESS +/** + * @var int + * @cvalue EAI_INPROGRESS + */ +const EAI_INPROGRESS = UNKNOWN; +#endif +#ifdef EAI_CANCELED +/** + * @var int + * @cvalue EAI_CANCELED + */ +const EAI_CANCELED = UNKNOWN; +#endif +#ifdef EAI_NOTCANCELED +/** + * @var int + * @cvalue EAI_NOTCANCELED + */ +const EAI_NOTCANCELED = UNKNOWN; +#endif +#ifdef EAI_ALLDONE +/** + * @var int + * @cvalue EAI_ALLDONE + */ +const EAI_ALLDONE = UNKNOWN; +#endif +#ifdef EAI_INTR +/** + * @var int + * @cvalue EAI_INTR + */ +const EAI_INTR = UNKNOWN; +#endif +#ifdef EAI_IDN_ENCODE +/** + * @var int + * @cvalue EAI_IDN_ENCODE + */ +const EAI_IDN_ENCODE = UNKNOWN; +#endif + /** * @strict-properties * @not-serializable @@ -2187,9 +2317,10 @@ function socket_cmsg_space(int $level, int $type, int $num = 0): ?int {} /** * @return array|false + * @param int $error_code * @refcount 1 */ -function socket_addrinfo_lookup(string $host, ?string $service = null, array $hints = []): array|false {} +function socket_addrinfo_lookup(string $host, ?string $service = null, array $hints = [], &$error_code = null): array|false {} function socket_addrinfo_connect(AddressInfo $address): Socket|false {} diff --git a/ext/sockets/sockets_arginfo.h b/ext/sockets/sockets_arginfo.h index 50a81c5ee3a74..522f356f853b2 100644 --- a/ext/sockets/sockets_arginfo.h +++ b/ext/sockets/sockets_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a89c4e54ab913728e10baf8f32b45323495d685b */ + * Stub hash: 5e71ef16f2121bd6c75794673d0e0a394759ff8b */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_select, 0, 4, MAY_BE_LONG|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(1, read, IS_ARRAY, 1) @@ -184,6 +184,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_socket_addrinfo_lookup, 0, 1, MA ZEND_ARG_TYPE_INFO(0, host, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, service, IS_STRING, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, hints, IS_ARRAY, 0, "[]") + ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, error_code, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_socket_addrinfo_connect, 0, 1, Socket, MAY_BE_FALSE) @@ -1054,6 +1055,60 @@ static void register_sockets_symbols(int module_number) REGISTER_LONG_CONSTANT("SHUT_WR", SHUT_WR, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SHUT_RDWR", SHUT_RDWR, CONST_PERSISTENT); #endif +#if defined(EAI_BADFLAGS) + REGISTER_LONG_CONSTANT("EAI_BADFLAGS", EAI_BADFLAGS, CONST_PERSISTENT); +#endif +#if defined(EAI_NONAME) + REGISTER_LONG_CONSTANT("EAI_NONAME", EAI_NONAME, CONST_PERSISTENT); +#endif +#if defined(EAI_AGAIN) + REGISTER_LONG_CONSTANT("EAI_AGAIN", EAI_AGAIN, CONST_PERSISTENT); +#endif +#if defined(EAI_FAIL) + REGISTER_LONG_CONSTANT("EAI_FAIL", EAI_FAIL, CONST_PERSISTENT); +#endif +#if defined(EAI_NODATA) + REGISTER_LONG_CONSTANT("EAI_NODATA", EAI_NODATA, CONST_PERSISTENT); +#endif +#if defined(EAI_FAMILY) + REGISTER_LONG_CONSTANT("EAI_FAMILY", EAI_FAMILY, CONST_PERSISTENT); +#endif +#if defined(EAI_SOCKTYPE) + REGISTER_LONG_CONSTANT("EAI_SOCKTYPE", EAI_SOCKTYPE, CONST_PERSISTENT); +#endif +#if defined(EAI_SERVICE) + REGISTER_LONG_CONSTANT("EAI_SERVICE", EAI_SERVICE, CONST_PERSISTENT); +#endif +#if defined(EAI_ADDRFAMILY) + REGISTER_LONG_CONSTANT("EAI_ADDRFAMILY", EAI_ADDRFAMILY, CONST_PERSISTENT); +#endif +#if !(defined(EAI_ADDRFAMILY)) && defined(EAI_FAMILY) + REGISTER_LONG_CONSTANT("EAI_ADDRFAMILY", EAI_FAMILY, CONST_PERSISTENT); +#endif +#if defined(EAI_SYSTEM) + REGISTER_LONG_CONSTANT("EAI_SYSTEM", EAI_SYSTEM, CONST_PERSISTENT); +#endif +#if defined(EAI_OVERFLOW) + REGISTER_LONG_CONSTANT("EAI_OVERFLOW", EAI_OVERFLOW, CONST_PERSISTENT); +#endif +#if defined(EAI_INPROGRESS) + REGISTER_LONG_CONSTANT("EAI_INPROGRESS", EAI_INPROGRESS, CONST_PERSISTENT); +#endif +#if defined(EAI_CANCELED) + REGISTER_LONG_CONSTANT("EAI_CANCELED", EAI_CANCELED, CONST_PERSISTENT); +#endif +#if defined(EAI_NOTCANCELED) + REGISTER_LONG_CONSTANT("EAI_NOTCANCELED", EAI_NOTCANCELED, CONST_PERSISTENT); +#endif +#if defined(EAI_ALLDONE) + REGISTER_LONG_CONSTANT("EAI_ALLDONE", EAI_ALLDONE, CONST_PERSISTENT); +#endif +#if defined(EAI_INTR) + REGISTER_LONG_CONSTANT("EAI_INTR", EAI_INTR, CONST_PERSISTENT); +#endif +#if defined(EAI_IDN_ENCODE) + REGISTER_LONG_CONSTANT("EAI_IDN_ENCODE", EAI_IDN_ENCODE, CONST_PERSISTENT); +#endif } static zend_class_entry *register_class_Socket(void) diff --git a/ext/sockets/tests/gh20532.phpt b/ext/sockets/tests/gh20532.phpt new file mode 100644 index 0000000000000..f3368c830369a --- /dev/null +++ b/ext/sockets/tests/gh20532.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-20562 - socket_addrinfo_lookup() returns error codes on resolution failures. +--EXTENSIONS-- +sockets +--FILE-- + AF_INET], $error_code) === false && in_array($error_code, [EAI_FAMILY, EAI_ADDRFAMILY, EAI_NONAME, EAI_NODATA])); +var_dump(socket_addrinfo_lookup("example.com", "http", ['ai_socktype' => SOCK_RAW, 'ai_flags' => 2147483647], $error_code) === false && in_array($error_code, [EAI_SOCKTYPE, EAI_SERVICE, EAI_BADFLAGS, EAI_NONAME])); +?> +--EXPECT-- +bool(true) +bool(true) +bool(true) + diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index 0acfcbc5c16d0..35cc7d426911d 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -34,7 +34,6 @@ #include "spl_heap.h" #include "zend_exceptions.h" #include "zend_interfaces.h" -#include "main/snprintf.h" ZEND_TLS zend_string *spl_autoload_extensions; ZEND_TLS HashTable *spl_autoload_functions; @@ -224,21 +223,19 @@ PHP_FUNCTION(spl_classes) } /* }}} */ -static int spl_autoload(zend_string *class_name, zend_string *lc_name, const char *ext, int ext_len) /* {{{ */ +static bool spl_autoload(zend_string *lc_name, const char *ext, size_t ext_len) /* {{{ */ { zend_string *class_file; zval dummy; zend_file_handle file_handle; - zend_op_array *new_op_array; zval result; - int ret; - class_file = zend_strpprintf(0, "%s%.*s", ZSTR_VAL(lc_name), ext_len, ext); + class_file = zend_string_concat2(ZSTR_VAL(lc_name), ZSTR_LEN(lc_name), ext, ext_len); #if DEFAULT_SLASH != '\\' { char *ptr = ZSTR_VAL(class_file); - char *end = ptr + ZSTR_LEN(class_file); + const char *end = ptr + ZSTR_LEN(class_file); while ((ptr = memchr(ptr, '\\', (end - ptr))) != NULL) { *ptr = DEFAULT_SLASH; @@ -246,22 +243,20 @@ static int spl_autoload(zend_string *class_name, zend_string *lc_name, const cha } #endif + bool ret = false; zend_stream_init_filename_ex(&file_handle, class_file); - ret = php_stream_open_for_zend_ex(&file_handle, USE_PATH|STREAM_OPEN_FOR_INCLUDE); - - if (ret == SUCCESS) { + if (php_stream_open_for_zend_ex(&file_handle, USE_PATH|STREAM_OPEN_FOR_INCLUDE) == SUCCESS) { zend_string *opened_path; if (!file_handle.opened_path) { file_handle.opened_path = zend_string_copy(class_file); } opened_path = zend_string_copy(file_handle.opened_path); ZVAL_NULL(&dummy); + zend_op_array *new_op_array = NULL; if (zend_hash_add(&EG(included_files), opened_path, &dummy)) { new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE); - } else { - new_op_array = NULL; } - zend_string_release_ex(opened_path, 0); + zend_string_release_ex(opened_path, false); if (new_op_array) { uint32_t orig_jit_trace_num = EG(jit_trace_num); @@ -271,24 +266,20 @@ static int spl_autoload(zend_string *class_name, zend_string *lc_name, const cha destroy_op_array(new_op_array); efree(new_op_array); - if (!EG(exception)) { - zval_ptr_dtor(&result); - } + zval_ptr_dtor(&result); - zend_destroy_file_handle(&file_handle); - zend_string_release(class_file); - return zend_hash_exists(EG(class_table), lc_name); + ret = zend_hash_exists(EG(class_table), lc_name); } } zend_destroy_file_handle(&file_handle); zend_string_release(class_file); - return 0; + return ret; } /* }}} */ /* {{{ Default autoloader implementation */ PHP_FUNCTION(spl_autoload) { - int pos_len, pos1_len; + size_t pos_len, pos1_len; char *pos, *pos1; zend_string *class_name, *lc_name, *file_exts = NULL; @@ -305,18 +296,18 @@ PHP_FUNCTION(spl_autoload) pos_len = sizeof(SPL_DEFAULT_FILE_EXTENSIONS) - 1; } else { pos = ZSTR_VAL(file_exts); - pos_len = (int)ZSTR_LEN(file_exts); + pos_len = ZSTR_LEN(file_exts); } lc_name = zend_string_tolower(class_name); while (pos && *pos && !EG(exception)) { pos1 = strchr(pos, ','); if (pos1) { - pos1_len = (int)(pos1 - pos); + pos1_len = (size_t)(pos1 - pos); } else { pos1_len = pos_len; } - if (spl_autoload(class_name, lc_name, pos, pos1_len)) { + if (spl_autoload(lc_name, pos, pos1_len)) { break; /* loaded */ } pos = pos1 ? pos1 + 1 : NULL; @@ -349,67 +340,11 @@ PHP_FUNCTION(spl_autoload_extensions) } } /* }}} */ -typedef struct { - zend_function *func_ptr; - zend_object *obj; - zend_object *closure; - zend_class_entry *ce; -} autoload_func_info; - -static void autoload_func_info_destroy(autoload_func_info *alfi) { - if (alfi->obj) { - zend_object_release(alfi->obj); - } - if (alfi->func_ptr && - UNEXPECTED(alfi->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { - zend_string_release_ex(alfi->func_ptr->common.function_name, 0); - zend_free_trampoline(alfi->func_ptr); - } - if (alfi->closure) { - zend_object_release(alfi->closure); - } - efree(alfi); -} - static void autoload_func_info_zval_dtor(zval *element) { - autoload_func_info_destroy(Z_PTR_P(element)); -} - -static autoload_func_info *autoload_func_info_from_fci( - zend_fcall_info *fci, zend_fcall_info_cache *fcc) { - autoload_func_info *alfi = emalloc(sizeof(autoload_func_info)); - alfi->ce = fcc->calling_scope; - alfi->func_ptr = fcc->function_handler; - alfi->obj = fcc->object; - if (alfi->obj) { - GC_ADDREF(alfi->obj); - } - if (Z_TYPE(fci->function_name) == IS_OBJECT) { - alfi->closure = Z_OBJ(fci->function_name); - GC_ADDREF(alfi->closure); - } else { - alfi->closure = NULL; - } - return alfi; -} - -static bool autoload_func_info_equals( - const autoload_func_info *alfi1, const autoload_func_info *alfi2) { - if (UNEXPECTED( - (alfi1->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) && - (alfi2->func_ptr->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) - )) { - return alfi1->obj == alfi2->obj - && alfi1->ce == alfi2->ce - && alfi1->closure == alfi2->closure - && zend_string_equals(alfi1->func_ptr->common.function_name, alfi2->func_ptr->common.function_name) - ; - } - return alfi1->func_ptr == alfi2->func_ptr - && alfi1->obj == alfi2->obj - && alfi1->ce == alfi2->ce - && alfi1->closure == alfi2->closure; + zend_fcall_info_cache *fcc = Z_PTR_P(element); + zend_fcc_dtor(fcc); + efree(fcc); } static zend_class_entry *spl_perform_autoload(zend_string *class_name, zend_string *lc_name) { @@ -421,34 +356,27 @@ static zend_class_entry *spl_perform_autoload(zend_string *class_name, zend_stri * because autoloaders may be added/removed during autoloading. */ HashPosition pos; zend_hash_internal_pointer_reset_ex(spl_autoload_functions, &pos); - while (1) { - autoload_func_info *alfi = + + zval zname; + ZVAL_STR(&zname, class_name); + while (true) { + zend_fcall_info_cache *fcc = zend_hash_get_current_data_ptr_ex(spl_autoload_functions, &pos); - if (!alfi) { + if (!fcc) { break; } - zend_function *func = alfi->func_ptr; - if (UNEXPECTED(func->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) { - func = emalloc(sizeof(zend_op_array)); - memcpy(func, alfi->func_ptr, sizeof(zend_op_array)); - zend_string_addref(func->op_array.function_name); - } - - zval param; - ZVAL_STR(¶m, class_name); - zend_call_known_function(func, alfi->obj, alfi->ce, NULL, 1, ¶m, NULL); - if (EG(exception)) { + zend_call_known_fcc(fcc, NULL, 1, &zname, NULL); + if (UNEXPECTED(EG(exception))) { break; } - if (ZSTR_HAS_CE_CACHE(class_name) && ZSTR_GET_CE_CACHE(class_name)) { + if (ZSTR_HAS_CE_CACHE(class_name) && ZSTR_GET_CE_CACHE(class_name)) { return (zend_class_entry*)ZSTR_GET_CE_CACHE(class_name); - } else { - zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), lc_name); - if (ce) { - return ce; - } + } + zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), lc_name); + if (ce != NULL) { + return ce; } zend_hash_move_forward_ex(spl_autoload_functions, &pos); @@ -470,24 +398,14 @@ PHP_FUNCTION(spl_autoload_call) zend_string_release(lc_name); } /* }}} */ -#define HT_MOVE_TAIL_TO_HEAD(ht) \ - ZEND_ASSERT(!HT_IS_PACKED(ht)); \ - do { \ - Bucket tmp = (ht)->arData[(ht)->nNumUsed-1]; \ - memmove((ht)->arData + 1, (ht)->arData, \ - sizeof(Bucket) * ((ht)->nNumUsed - 1)); \ - (ht)->arData[0] = tmp; \ - zend_hash_rehash(ht); \ - } while (0) - -static Bucket *spl_find_registered_function(autoload_func_info *find_alfi) { +static Bucket *spl_find_registered_function(const zend_fcall_info_cache *find_fcc) { if (!spl_autoload_functions) { return NULL; } - autoload_func_info *alfi; - ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, alfi) { - if (autoload_func_info_equals(alfi, find_alfi)) { + zend_fcall_info_cache *fcc; + ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, fcc) { + if (zend_fcc_equals(fcc, find_fcc)) { return _p; } } ZEND_HASH_FOREACH_END(); @@ -501,7 +419,6 @@ PHP_FUNCTION(spl_autoload_register) bool prepend = 0; zend_fcall_info fci = {0}; zend_fcall_info_cache fcc; - autoload_func_info *alfi; ZEND_PARSE_PARAMETERS_START(0, 3) Z_PARAM_OPTIONAL @@ -517,14 +434,14 @@ PHP_FUNCTION(spl_autoload_register) if (!spl_autoload_functions) { ALLOC_HASHTABLE(spl_autoload_functions); - zend_hash_init(spl_autoload_functions, 1, NULL, autoload_func_info_zval_dtor, 0); + zend_hash_init(spl_autoload_functions, 1, NULL, autoload_func_info_zval_dtor, false); /* Initialize as non-packed hash table for prepend functionality. */ zend_hash_real_init_mixed(spl_autoload_functions); } /* If first arg is not null */ if (ZEND_FCI_INITIALIZED(fci)) { - if (!fcc.function_handler) { + if (!ZEND_FCC_INITIALIZED(fcc)) { /* Call trampoline has been cleared by zpp. Refetch it, because we want to deal * with it ourselves. It is important that it is not refetched on every call, * because calls may occur from different scopes. */ @@ -536,33 +453,26 @@ PHP_FUNCTION(spl_autoload_register) zend_argument_value_error(1, "must not be the spl_autoload_call() function"); RETURN_THROWS(); } - - alfi = autoload_func_info_from_fci(&fci, &fcc); - if (UNEXPECTED(alfi->func_ptr == &EG(trampoline))) { - zend_function *copy = emalloc(sizeof(zend_op_array)); - - memcpy(copy, alfi->func_ptr, sizeof(zend_op_array)); - alfi->func_ptr->common.function_name = NULL; - alfi->func_ptr = copy; - } } else { - alfi = emalloc(sizeof(autoload_func_info)); - alfi->func_ptr = zend_hash_str_find_ptr( - CG(function_table), "spl_autoload", sizeof("spl_autoload") - 1); - alfi->obj = NULL; - alfi->ce = NULL; - alfi->closure = NULL; + memset(&fcc, 0, sizeof(fcc)); + fcc.function_handler = zend_hash_str_find_ptr(CG(function_table), ZEND_STRL("spl_autoload")); } - if (spl_find_registered_function(alfi)) { - autoload_func_info_destroy(alfi); + if (spl_find_registered_function(&fcc)) { + /* Release call trampoline */ + zend_release_fcall_info_cache(&fcc); RETURN_TRUE; } - zend_hash_next_index_insert_ptr(spl_autoload_functions, alfi); + zend_fcc_addref(&fcc); + zend_hash_next_index_insert_mem(spl_autoload_functions, &fcc, sizeof(zend_fcall_info_cache)); if (prepend && spl_autoload_functions->nNumOfElements > 1) { /* Move the newly created element to the head of the hashtable */ - HT_MOVE_TAIL_TO_HEAD(spl_autoload_functions); + ZEND_ASSERT(!HT_IS_PACKED(spl_autoload_functions)); + Bucket tmp = spl_autoload_functions->arData[spl_autoload_functions->nNumUsed-1]; + memmove(spl_autoload_functions->arData + 1, spl_autoload_functions->arData, sizeof(Bucket) * (spl_autoload_functions->nNumUsed - 1)); + spl_autoload_functions->arData[0] = tmp; + zend_hash_rehash(spl_autoload_functions); } RETURN_TRUE; @@ -575,11 +485,12 @@ PHP_FUNCTION(spl_autoload_unregister) zend_fcall_info_cache fcc; ZEND_PARSE_PARAMETERS_START(1, 1) - Z_PARAM_FUNC(fci, fcc) + Z_PARAM_FUNC_NO_TRAMPOLINE_FREE(fci, fcc) ZEND_PARSE_PARAMETERS_END(); - if (fcc.function_handler && zend_string_equals_literal( - fcc.function_handler->common.function_name, "spl_autoload_call")) { + if (zend_string_equals_literal(fcc.function_handler->common.function_name, "spl_autoload_call")) { + /* Release trampoline */ + zend_release_fcall_info_cache(&fcc); php_error_docref(NULL, E_DEPRECATED, "Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated," " to remove all registered autoloaders, call spl_autoload_unregister()" @@ -594,16 +505,9 @@ PHP_FUNCTION(spl_autoload_unregister) RETURN_TRUE; } - if (!fcc.function_handler) { - /* Call trampoline has been cleared by zpp. Refetch it, because we want to deal - * with it ourselves. It is important that it is not refetched on every call, - * because calls may occur from different scopes. */ - zend_is_callable_ex(&fci.function_name, NULL, 0, NULL, &fcc, NULL); - } - - autoload_func_info *alfi = autoload_func_info_from_fci(&fci, &fcc); - Bucket *p = spl_find_registered_function(alfi); - autoload_func_info_destroy(alfi); + Bucket *p = spl_find_registered_function(&fcc); + /* Release trampoline */ + zend_release_fcall_info_cache(&fcc); if (p) { zend_hash_del_bucket(spl_autoload_functions, p); RETURN_TRUE; @@ -615,32 +519,19 @@ PHP_FUNCTION(spl_autoload_unregister) /* {{{ Return all registered autoloader functions */ PHP_FUNCTION(spl_autoload_functions) { - autoload_func_info *alfi; - ZEND_PARSE_PARAMETERS_NONE(); - array_init(return_value); if (spl_autoload_functions) { - ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, alfi) { - if (alfi->closure) { - GC_ADDREF(alfi->closure); - add_next_index_object(return_value, alfi->closure); - } else if (alfi->func_ptr->common.scope) { - zval tmp; - - array_init(&tmp); - if (alfi->obj) { - GC_ADDREF(alfi->obj); - add_next_index_object(&tmp, alfi->obj); - } else { - add_next_index_str(&tmp, zend_string_copy(alfi->ce->name)); - } - add_next_index_str(&tmp, zend_string_copy(alfi->func_ptr->common.function_name)); - add_next_index_zval(return_value, &tmp); - } else { - add_next_index_str(return_value, zend_string_copy(alfi->func_ptr->common.function_name)); - } + zend_fcall_info_cache *fcc; + + array_init_size(return_value, zend_hash_num_elements(spl_autoload_functions)); + ZEND_HASH_MAP_FOREACH_PTR(spl_autoload_functions, fcc) { + zval tmp; + zend_get_callable_zval_from_fcc(fcc, &tmp); + add_next_index_zval(return_value, &tmp); } ZEND_HASH_FOREACH_END(); + } else { + RETURN_EMPTY_ARRAY(); } } /* }}} */ diff --git a/ext/spl/tests/bug38325.phpt b/ext/spl/tests/autoloading/bug38325.phpt similarity index 100% rename from ext/spl/tests/bug38325.phpt rename to ext/spl/tests/autoloading/bug38325.phpt diff --git a/ext/spl/tests/bug40091.phpt b/ext/spl/tests/autoloading/bug40091.phpt similarity index 100% rename from ext/spl/tests/bug40091.phpt rename to ext/spl/tests/autoloading/bug40091.phpt diff --git a/ext/spl/tests/bug44144.phpt b/ext/spl/tests/autoloading/bug44144.phpt similarity index 100% rename from ext/spl/tests/bug44144.phpt rename to ext/spl/tests/autoloading/bug44144.phpt diff --git a/ext/spl/tests/bug48023.phpt b/ext/spl/tests/autoloading/bug48023.phpt similarity index 100% rename from ext/spl/tests/bug48023.phpt rename to ext/spl/tests/autoloading/bug48023.phpt diff --git a/ext/spl/tests/bug48493.phpt b/ext/spl/tests/autoloading/bug48493.phpt similarity index 100% rename from ext/spl/tests/bug48493.phpt rename to ext/spl/tests/autoloading/bug48493.phpt diff --git a/ext/spl/tests/bug52339.phpt b/ext/spl/tests/autoloading/bug52339.phpt similarity index 100% rename from ext/spl/tests/bug52339.phpt rename to ext/spl/tests/autoloading/bug52339.phpt diff --git a/ext/spl/tests/bug61697.phpt b/ext/spl/tests/autoloading/bug61697.phpt similarity index 100% rename from ext/spl/tests/bug61697.phpt rename to ext/spl/tests/autoloading/bug61697.phpt diff --git a/ext/spl/tests/bug65006.phpt b/ext/spl/tests/autoloading/bug65006.phpt similarity index 100% rename from ext/spl/tests/bug65006.phpt rename to ext/spl/tests/autoloading/bug65006.phpt diff --git a/ext/spl/tests/bug71202.phpt b/ext/spl/tests/autoloading/bug71202.phpt similarity index 100% rename from ext/spl/tests/bug71202.phpt rename to ext/spl/tests/autoloading/bug71202.phpt diff --git a/ext/spl/tests/bug71204.phpt b/ext/spl/tests/autoloading/bug71204.phpt similarity index 100% rename from ext/spl/tests/bug71204.phpt rename to ext/spl/tests/autoloading/bug71204.phpt diff --git a/ext/spl/tests/bug71236.phpt b/ext/spl/tests/autoloading/bug71236.phpt similarity index 100% rename from ext/spl/tests/bug71236.phpt rename to ext/spl/tests/autoloading/bug71236.phpt diff --git a/ext/spl/tests/bug73896.phpt b/ext/spl/tests/autoloading/bug73896.phpt similarity index 100% rename from ext/spl/tests/bug73896.phpt rename to ext/spl/tests/autoloading/bug73896.phpt diff --git a/ext/spl/tests/bug74372.phpt b/ext/spl/tests/autoloading/bug74372.phpt similarity index 100% rename from ext/spl/tests/bug74372.phpt rename to ext/spl/tests/autoloading/bug74372.phpt diff --git a/ext/spl/tests/bug75049.phpt b/ext/spl/tests/autoloading/bug75049.phpt similarity index 100% rename from ext/spl/tests/bug75049.phpt rename to ext/spl/tests/autoloading/bug75049.phpt diff --git a/ext/spl/tests/gh10011.phpt b/ext/spl/tests/autoloading/gh10011.phpt similarity index 100% rename from ext/spl/tests/gh10011.phpt rename to ext/spl/tests/autoloading/gh10011.phpt diff --git a/ext/spl/tests/spl_autoload_001.phpt b/ext/spl/tests/autoloading/spl_autoload_001.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_001.phpt rename to ext/spl/tests/autoloading/spl_autoload_001.phpt diff --git a/ext/spl/tests/spl_autoload_002.phpt b/ext/spl/tests/autoloading/spl_autoload_002.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_002.phpt rename to ext/spl/tests/autoloading/spl_autoload_002.phpt diff --git a/ext/spl/tests/spl_autoload_003.phpt b/ext/spl/tests/autoloading/spl_autoload_003.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_003.phpt rename to ext/spl/tests/autoloading/spl_autoload_003.phpt diff --git a/ext/spl/tests/spl_autoload_004.phpt b/ext/spl/tests/autoloading/spl_autoload_004.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_004.phpt rename to ext/spl/tests/autoloading/spl_autoload_004.phpt diff --git a/ext/spl/tests/spl_autoload_005.phpt b/ext/spl/tests/autoloading/spl_autoload_005.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_005.phpt rename to ext/spl/tests/autoloading/spl_autoload_005.phpt diff --git a/ext/spl/tests/spl_autoload_006.phpt b/ext/spl/tests/autoloading/spl_autoload_006.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_006.phpt rename to ext/spl/tests/autoloading/spl_autoload_006.phpt diff --git a/ext/spl/tests/spl_autoload_007.phpt b/ext/spl/tests/autoloading/spl_autoload_007.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_007.phpt rename to ext/spl/tests/autoloading/spl_autoload_007.phpt diff --git a/ext/spl/tests/spl_autoload_008.phpt b/ext/spl/tests/autoloading/spl_autoload_008.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_008.phpt rename to ext/spl/tests/autoloading/spl_autoload_008.phpt diff --git a/ext/spl/tests/spl_autoload_009.phpt b/ext/spl/tests/autoloading/spl_autoload_009.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_009.phpt rename to ext/spl/tests/autoloading/spl_autoload_009.phpt diff --git a/ext/spl/tests/spl_autoload_010.phpt b/ext/spl/tests/autoloading/spl_autoload_010.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_010.phpt rename to ext/spl/tests/autoloading/spl_autoload_010.phpt diff --git a/ext/spl/tests/spl_autoload_011.phpt b/ext/spl/tests/autoloading/spl_autoload_011.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_011.phpt rename to ext/spl/tests/autoloading/spl_autoload_011.phpt diff --git a/ext/spl/tests/spl_autoload_012.phpt b/ext/spl/tests/autoloading/spl_autoload_012.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_012.phpt rename to ext/spl/tests/autoloading/spl_autoload_012.phpt diff --git a/ext/spl/tests/spl_autoload_013.phpt b/ext/spl/tests/autoloading/spl_autoload_013.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_013.phpt rename to ext/spl/tests/autoloading/spl_autoload_013.phpt diff --git a/ext/spl/tests/spl_autoload_014.phpt b/ext/spl/tests/autoloading/spl_autoload_014.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_014.phpt rename to ext/spl/tests/autoloading/spl_autoload_014.phpt diff --git a/ext/spl/tests/spl_autoload_bug48541.phpt b/ext/spl/tests/autoloading/spl_autoload_bug48541.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_bug48541.phpt rename to ext/spl/tests/autoloading/spl_autoload_bug48541.phpt diff --git a/ext/spl/tests/spl_autoload_call_basic.phpt b/ext/spl/tests/autoloading/spl_autoload_call_basic.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_call_basic.phpt rename to ext/spl/tests/autoloading/spl_autoload_call_basic.phpt diff --git a/ext/spl/tests/spl_autoload_called_scope.phpt b/ext/spl/tests/autoloading/spl_autoload_called_scope.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_called_scope.phpt rename to ext/spl/tests/autoloading/spl_autoload_called_scope.phpt diff --git a/ext/spl/tests/spl_autoload_throw_with_spl_autoloader_call_as_autoloader.phpt b/ext/spl/tests/autoloading/spl_autoload_throw_with_spl_autoloader_call_as_autoloader.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_throw_with_spl_autoloader_call_as_autoloader.phpt rename to ext/spl/tests/autoloading/spl_autoload_throw_with_spl_autoloader_call_as_autoloader.phpt diff --git a/ext/spl/tests/spl_autoload_unregister_without_registrations.phpt b/ext/spl/tests/autoloading/spl_autoload_unregister_without_registrations.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_unregister_without_registrations.phpt rename to ext/spl/tests/autoloading/spl_autoload_unregister_without_registrations.phpt diff --git a/ext/spl/tests/spl_autoload_warn_on_false_do_throw.phpt b/ext/spl/tests/autoloading/spl_autoload_warn_on_false_do_throw.phpt similarity index 100% rename from ext/spl/tests/spl_autoload_warn_on_false_do_throw.phpt rename to ext/spl/tests/autoloading/spl_autoload_warn_on_false_do_throw.phpt diff --git a/ext/spl/tests/testclass b/ext/spl/tests/autoloading/testclass similarity index 100% rename from ext/spl/tests/testclass rename to ext/spl/tests/autoloading/testclass diff --git a/ext/spl/tests/testclass.class.inc b/ext/spl/tests/autoloading/testclass.class.inc similarity index 100% rename from ext/spl/tests/testclass.class.inc rename to ext/spl/tests/autoloading/testclass.class.inc diff --git a/ext/spl/tests/testclass.inc b/ext/spl/tests/autoloading/testclass.inc similarity index 100% rename from ext/spl/tests/testclass.inc rename to ext/spl/tests/autoloading/testclass.inc diff --git a/ext/spl/tests/testclass.php.inc b/ext/spl/tests/autoloading/testclass.php.inc similarity index 100% rename from ext/spl/tests/testclass.php.inc rename to ext/spl/tests/autoloading/testclass.php.inc diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index da24b037861a8..6d55409ca45aa 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -1270,13 +1270,10 @@ PHP_METHOD(SQLite3, openBlob) mode = "r+b"; } + // since it is not persistent, php_stream_alloc can't fail stream = php_stream_alloc(&php_stream_sqlite3_ops, sqlite3_stream, 0, mode); - - if (stream) { - php_stream_to_zval(stream, return_value); - } else { - RETURN_FALSE; - } + ZEND_ASSERT(stream != NULL); + php_stream_to_zval(stream, return_value); } /* }}} */