diff --git a/Zend/zend_autoload.c b/Zend/zend_autoload.c index 253143a9b22d1..bc74efa1afdaa 100644 --- a/Zend/zend_autoload.c +++ b/Zend/zend_autoload.c @@ -28,139 +28,139 @@ ZEND_TLS HashTable *zend_class_autoload_functions; static void zend_autoload_callback_zval_destroy(zval *element) { - zend_fcall_info_cache *fcc = Z_PTR_P(element); - zend_fcc_dtor(fcc); - efree(fcc); + zend_fcall_info_cache *fcc = Z_PTR_P(element); + zend_fcc_dtor(fcc); + efree(fcc); } static Bucket *autoload_find_registered_function(const HashTable *autoloader_table, const zend_fcall_info_cache *function_entry) { - zend_fcall_info_cache *current_function_entry; - ZEND_HASH_MAP_FOREACH_PTR(autoloader_table, current_function_entry) { - if (zend_fcc_equals(current_function_entry, function_entry)) { - return _p; - } - } ZEND_HASH_FOREACH_END(); - return NULL; + zend_fcall_info_cache *current_function_entry; + ZEND_HASH_MAP_FOREACH_PTR(autoloader_table, current_function_entry) { + if (zend_fcc_equals(current_function_entry, function_entry)) { + return _p; + } + } ZEND_HASH_FOREACH_END(); + return NULL; } ZEND_API zend_class_entry *zend_perform_class_autoload(zend_string *class_name, zend_string *lc_name) { - if (!zend_class_autoload_functions) { - return NULL; - } - - zval zname; - ZVAL_STR(&zname, class_name); - - const HashTable *class_autoload_functions = zend_class_autoload_functions; - - /* Cannot use ZEND_HASH_MAP_FOREACH_PTR here as autoloaders may be - * added/removed during autoloading. */ - HashPosition pos; - zend_hash_internal_pointer_reset_ex(class_autoload_functions, &pos); - while (true) { - zend_fcall_info_cache *func_info = zend_hash_get_current_data_ptr_ex(class_autoload_functions, &pos); - if (!func_info) { - break; - } - zend_call_known_fcc(func_info, /* retval */ NULL, /* param_count */ 1, /* params */ &zname, /* named_params */ NULL); - - if (EG(exception)) { - return NULL; - } - if (ZSTR_HAS_CE_CACHE(class_name) && ZSTR_GET_CE_CACHE(class_name)) { - return (zend_class_entry*)ZSTR_GET_CE_CACHE(class_name); - } - - zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), lc_name); - if (ce) { - return ce; - } - - zend_hash_move_forward_ex(class_autoload_functions, &pos); - } - return NULL; + if (!zend_class_autoload_functions) { + return NULL; + } + + zval zname; + ZVAL_STR(&zname, class_name); + + const HashTable *class_autoload_functions = zend_class_autoload_functions; + + /* Cannot use ZEND_HASH_MAP_FOREACH_PTR here as autoloaders may be + * added/removed during autoloading. */ + HashPosition pos; + zend_hash_internal_pointer_reset_ex(class_autoload_functions, &pos); + while (true) { + zend_fcall_info_cache *func_info = zend_hash_get_current_data_ptr_ex(class_autoload_functions, &pos); + if (!func_info) { + break; + } + zend_call_known_fcc(func_info, /* retval */ NULL, /* param_count */ 1, /* params */ &zname, /* named_params */ NULL); + + if (EG(exception)) { + return NULL; + } + if (ZSTR_HAS_CE_CACHE(class_name) && ZSTR_GET_CE_CACHE(class_name)) { + return (zend_class_entry*)ZSTR_GET_CE_CACHE(class_name); + } + + zend_class_entry *ce = zend_hash_find_ptr(EG(class_table), lc_name); + if (ce) { + return ce; + } + + zend_hash_move_forward_ex(class_autoload_functions, &pos); + } + return NULL; } /* Needed for compatibility with spl_register_autoload() */ ZEND_API void zend_autoload_register_class_loader(zend_fcall_info_cache *fcc, bool prepend) { - ZEND_ASSERT(ZEND_FCC_INITIALIZED(*fcc)); - - if (!zend_class_autoload_functions) { - ALLOC_HASHTABLE(zend_class_autoload_functions); - zend_hash_init(zend_class_autoload_functions, 1, NULL, zend_autoload_callback_zval_destroy, false); - /* Initialize as non-packed hash table for prepend functionality. */ - zend_hash_real_init_mixed(zend_class_autoload_functions); - } - - ZEND_ASSERT( - fcc->function_handler->type != ZEND_INTERNAL_FUNCTION - || !zend_string_equals_literal(fcc->function_handler->common.function_name, "spl_autoload_call") - ); - - /* If function is already registered, don't do anything */ - if (autoload_find_registered_function(zend_class_autoload_functions, fcc)) { - /* Release potential call trampoline */ - zend_release_fcall_info_cache(fcc); - return; - } - - zend_fcc_addref(fcc); - zend_hash_next_index_insert_mem(zend_class_autoload_functions, fcc, sizeof(zend_fcall_info_cache)); - if (prepend && zend_hash_num_elements(zend_class_autoload_functions) > 1) { - /* Move the newly created element to the head of the hashtable */ - ZEND_ASSERT(!HT_IS_PACKED(zend_class_autoload_functions)); - Bucket tmp = zend_class_autoload_functions->arData[zend_class_autoload_functions->nNumUsed-1]; - memmove(zend_class_autoload_functions->arData + 1, zend_class_autoload_functions->arData, sizeof(Bucket) * (zend_class_autoload_functions->nNumUsed - 1)); - zend_class_autoload_functions->arData[0] = tmp; - zend_hash_rehash(zend_class_autoload_functions); - } + ZEND_ASSERT(ZEND_FCC_INITIALIZED(*fcc)); + + if (!zend_class_autoload_functions) { + ALLOC_HASHTABLE(zend_class_autoload_functions); + zend_hash_init(zend_class_autoload_functions, 1, NULL, zend_autoload_callback_zval_destroy, false); + /* Initialize as non-packed hash table for prepend functionality. */ + zend_hash_real_init_mixed(zend_class_autoload_functions); + } + + ZEND_ASSERT( + fcc->function_handler->type != ZEND_INTERNAL_FUNCTION + || !zend_string_equals_literal(fcc->function_handler->common.function_name, "spl_autoload_call") + ); + + /* If function is already registered, don't do anything */ + if (autoload_find_registered_function(zend_class_autoload_functions, fcc)) { + /* Release potential call trampoline */ + zend_release_fcall_info_cache(fcc); + return; + } + + zend_fcc_addref(fcc); + zend_hash_next_index_insert_mem(zend_class_autoload_functions, fcc, sizeof(zend_fcall_info_cache)); + if (prepend && zend_hash_num_elements(zend_class_autoload_functions) > 1) { + /* Move the newly created element to the head of the hashtable */ + ZEND_ASSERT(!HT_IS_PACKED(zend_class_autoload_functions)); + Bucket tmp = zend_class_autoload_functions->arData[zend_class_autoload_functions->nNumUsed-1]; + memmove(zend_class_autoload_functions->arData + 1, zend_class_autoload_functions->arData, sizeof(Bucket) * (zend_class_autoload_functions->nNumUsed - 1)); + zend_class_autoload_functions->arData[0] = tmp; + zend_hash_rehash(zend_class_autoload_functions); + } } ZEND_API bool zend_autoload_unregister_class_loader(const zend_fcall_info_cache *fcc) { - if (zend_class_autoload_functions) { - Bucket *p = autoload_find_registered_function(zend_class_autoload_functions, fcc); - if (p) { - zend_hash_del_bucket(zend_class_autoload_functions, p); - return true; - } - } - return false; + if (zend_class_autoload_functions) { + Bucket *p = autoload_find_registered_function(zend_class_autoload_functions, fcc); + if (p) { + zend_hash_del_bucket(zend_class_autoload_functions, p); + return true; + } + } + return false; } /* We do not return a HashTable* because zend_empty_array is not collectable, * therefore the zval holding this value must do so. Something that ZVAL_EMPTY_ARRAY(); does. */ ZEND_API void zend_autoload_fcc_map_to_callable_zval_map(zval *return_value) { - if (zend_class_autoload_functions) { - zend_fcall_info_cache *fcc; - - zend_array *map = zend_new_array(zend_hash_num_elements(zend_class_autoload_functions)); - ZEND_HASH_MAP_FOREACH_PTR(zend_class_autoload_functions, fcc) { - zval tmp; - zend_get_callable_zval_from_fcc(fcc, &tmp); - zend_hash_next_index_insert(map, &tmp); - } ZEND_HASH_FOREACH_END(); - RETURN_ARR(map); - } - RETURN_EMPTY_ARRAY(); + if (zend_class_autoload_functions) { + zend_fcall_info_cache *fcc; + + zend_array *map = zend_new_array(zend_hash_num_elements(zend_class_autoload_functions)); + ZEND_HASH_MAP_FOREACH_PTR(zend_class_autoload_functions, fcc) { + zval tmp; + zend_get_callable_zval_from_fcc(fcc, &tmp); + zend_hash_next_index_insert(map, &tmp); + } ZEND_HASH_FOREACH_END(); + RETURN_ARR(map); + } + RETURN_EMPTY_ARRAY(); } /* Only for deprecated strange behaviour of spl_autoload_unregister() */ ZEND_API void zend_autoload_clean_class_loaders(void) { - if (zend_class_autoload_functions) { - /* Don't destroy the hash table, as we might be iterating over it right now. */ - zend_hash_clean(zend_class_autoload_functions); - } + if (zend_class_autoload_functions) { + /* Don't destroy the hash table, as we might be iterating over it right now. */ + zend_hash_clean(zend_class_autoload_functions); + } } void zend_autoload_shutdown(void) { - if (zend_class_autoload_functions) { - zend_hash_destroy(zend_class_autoload_functions); - FREE_HASHTABLE(zend_class_autoload_functions); - zend_class_autoload_functions = NULL; - } + if (zend_class_autoload_functions) { + zend_hash_destroy(zend_class_autoload_functions); + FREE_HASHTABLE(zend_class_autoload_functions); + zend_class_autoload_functions = NULL; + } } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index fb04387a0045a..d2d0090a70732 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -7896,7 +7896,7 @@ static bool zend_property_hook_uses_property(const zend_string *property_name, c return context.uses_property; } -static bool zend_property_is_virtual(const zend_class_entry *ce, const zend_string *property_name, zend_ast *hooks_ast, uint32_t flags) +static bool zend_property_is_virtual(const zend_class_entry *ce, const zend_string *property_name, zend_ast *hooks_ast) { if (ce->ce_flags & ZEND_ACC_INTERFACE) { return true; @@ -8172,7 +8172,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32 doc_comment_ast ? zend_string_copy(zend_ast_get_str(doc_comment_ast)) : NULL; zend_property_info *prop = zend_declare_typed_property( scope, name, &default_value, - property_flags | (zend_property_is_virtual(scope, name, hooks_ast, property_flags) ? ZEND_ACC_VIRTUAL : 0) | ZEND_ACC_PROMOTED, + property_flags | (zend_property_is_virtual(scope, name, hooks_ast) ? ZEND_ACC_VIRTUAL : 0) | ZEND_ACC_PROMOTED, doc_comment, type); if (hooks_ast) { const zend_ast_list *hooks = zend_ast_get_list(hooks_ast); @@ -9074,7 +9074,7 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f zend_string *doc_comment = NULL; zval value_zv; zend_type type = ZEND_TYPE_INIT_NONE(0); - flags |= zend_property_is_virtual(ce, name, hooks_ast, flags) ? ZEND_ACC_VIRTUAL : 0; + flags |= zend_property_is_virtual(ce, name, hooks_ast) ? ZEND_ACC_VIRTUAL : 0; zend_string *old_active_property_info_name = CG(context).active_property_info_name; CG(context).active_property_info_name = name; diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 62a55b4df5287..79785d3ced616 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -575,6 +575,10 @@ static int curl_fnmatch(void *ctx, const char *pattern, const char *string) zval argv[3]; zval retval; + if (!ZEND_FCC_INITIALIZED(ch->handlers.fnmatch)) { + return rval; + } + GC_ADDREF(&ch->std); ZVAL_OBJ(&argv[0], &ch->std); ZVAL_STRING(&argv[1], pattern); @@ -606,6 +610,9 @@ static int curl_progress(void *clientp, double dltotal, double dlnow, double ult fprintf(stderr, "curl_progress() called\n"); fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow); #endif + if (!ZEND_FCC_INITIALIZED(ch->handlers.progress)) { + return rval; + } zval args[5]; zval retval; @@ -644,6 +651,9 @@ static int curl_xferinfo(void *clientp, curl_off_t dltotal, curl_off_t dlnow, cu fprintf(stderr, "curl_xferinfo() called\n"); fprintf(stderr, "clientp = %x, dltotal = %ld, dlnow = %ld, ultotal = %ld, ulnow = %ld\n", clientp, dltotal, dlnow, ultotal, ulnow); #endif + if (!ZEND_FCC_INITIALIZED(ch->handlers.xferinfo)) { + return rval; + } zval argv[5]; zval retval; diff --git a/ext/curl/tests/gh21023.phpt b/ext/curl/tests/gh21023.phpt new file mode 100644 index 0000000000000..9647bd7baadd5 --- /dev/null +++ b/ext/curl/tests/gh21023.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-21023 (crash with CURLOPT_XFERINFOFUNCTION set with an invalid callback) +--EXTENSIONS-- +curl +--FILE-- + +--EXPECT-- +OK diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index 63f5c222c1924..ffba1192f0581 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -40,9 +40,7 @@ static zend_class_entry *php_ftp_ce = NULL; static zend_object_handlers ftp_object_handlers; zend_module_entry php_ftp_module_entry = { - STANDARD_MODULE_HEADER_EX, - NULL, - NULL, + STANDARD_MODULE_HEADER, "ftp", ext_functions, PHP_MINIT(ftp), diff --git a/ext/opcache/jit/ir/ir_gcm.c b/ext/opcache/jit/ir/ir_gcm.c index 67c97611eaac4..1a9e618823b39 100644 --- a/ext/opcache/jit/ir/ir_gcm.c +++ b/ext/opcache/jit/ir/ir_gcm.c @@ -262,7 +262,7 @@ static bool ir_split_partially_dead_node(ir_ctx *ctx, ir_ref ref, uint32_t b) #endif /* 1.2. Iteratively check the predecessors of already found TOTALLY_USEFUL blocks and - * add them into TOTALLY_USEFUL set if all of their sucessors are already there. + * add them into TOTALLY_USEFUL set if all of their successors are already there. */ IR_SPARSE_SET_FOREACH(&data->totally_useful, i) { _push_predecessors(ctx, &ctx->cfg_blocks[i], data);