From: Dmitry Stogov Date: Thu, 1 Dec 2005 11:49:51 +0000 (+0000) Subject: Fixed bug #34729 (Crash in ZTS mode under Apache) X-Git-Tag: RELEASE_2_0_2~7 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=feaa2501d0c099d72045af63f561b6151b46ed38;p=php Fixed bug #34729 (Crash in ZTS mode under Apache) --- diff --git a/Zend/zend.c b/Zend/zend.c index 88eb8f3cce..ad5f4a8622 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -970,6 +970,13 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS } else { compiler_globals->global_u_auto_globals_table = NULL; } + + compiler_globals->last_static_member = zend_hash_num_elements(compiler_globals->class_table); + if (compiler_globals->last_static_member) { + compiler_globals->static_members = (HashTable**)calloc(compiler_globals->last_static_member, sizeof(HashTable*)); + } else { + compiler_globals->static_members = NULL; + } } @@ -1008,6 +1015,10 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS free(compiler_globals->global_u_auto_globals_table); } } + if (compiler_globals->static_members) { + free(compiler_globals->static_members); + } + compiler_globals->last_static_member = 0; } diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 198d2b54c2..9cd3096d0a 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1115,22 +1115,26 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties, int destro ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC) { - if (!class_type->constants_updated || !class_type->static_members) { + if (!class_type->constants_updated || !CE_STATIC_MEMBERS(class_type)) { zend_class_entry **scope = EG(in_execution)?&EG(scope):&CG(active_class_entry); zend_class_entry *old_scope = *scope; *scope = class_type; zend_hash_apply_with_argument(&class_type->default_properties, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); - if (!class_type->static_members) { + if (!CE_STATIC_MEMBERS(class_type)) { HashPosition pos; zval **p; if (class_type->parent) { zend_update_class_constants(class_type->parent TSRMLS_CC); } +#if ZTS + ALLOC_HASHTABLE(CG(static_members)[(long)(class_type->static_members)]); +#else ALLOC_HASHTABLE(class_type->static_members); - zend_u_hash_init(class_type->static_members, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode)); +#endif + zend_u_hash_init(CE_STATIC_MEMBERS(class_type), 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode)); zend_hash_internal_pointer_reset_ex(&class_type->default_static_members, &pos); while (zend_hash_get_current_data_ex(&class_type->default_static_members, (void**)&p, &pos) == SUCCESS) { @@ -1156,10 +1160,10 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC class_type->parent && zend_u_hash_find(&class_type->parent->default_static_members, utype, str_index, str_length, (void**)&q) == SUCCESS && *p == *q && - zend_u_hash_find(class_type->parent->static_members, utype, str_index, str_length, (void**)&q) == SUCCESS) { + zend_u_hash_find(CE_STATIC_MEMBERS(class_type->parent), utype, str_index, str_length, (void**)&q) == SUCCESS) { (*q)->refcount++; (*q)->is_ref = 1; - zend_u_hash_add(class_type->static_members, utype, str_index, str_length, (void**)q, sizeof(zval*), NULL); + zend_u_hash_add(CE_STATIC_MEMBERS(class_type), utype, str_index, str_length, (void**)q, sizeof(zval*), NULL); } else { zval *q; @@ -1167,12 +1171,12 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC *q = **p; INIT_PZVAL(q); zval_copy_ctor(q); - zend_u_hash_add(class_type->static_members, utype, str_index, str_length, (void**)&q, sizeof(zval*), NULL); + zend_u_hash_add(CE_STATIC_MEMBERS(class_type), utype, str_index, str_length, (void**)&q, sizeof(zval*), NULL); } zend_hash_move_forward_ex(&class_type->default_static_members, &pos); } } - zend_hash_apply_with_argument(class_type->static_members, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); + zend_hash_apply_with_argument(CE_STATIC_MEMBERS(class_type), (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); *scope = old_scope; class_type->constants_updated = 1; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 92c3716b19..c22dd00bd1 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -152,6 +152,12 @@ typedef struct _zend_function_entry { #define INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset) \ INIT_OVERLOADED_CLASS_ENTRY_EX(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset, NULL, NULL) +#ifdef ZTS +# define CE_STATIC_MEMBERS(ce) (((ce)->type==ZEND_USER_CLASS)?(ce)->static_members:CG(static_members)[(long)(ce)->static_members]) +#else +# define CE_STATIC_MEMBERS(ce) ((ce)->static_members) +#endif + int zend_next_free_module(void); BEGIN_EXTERN_C() diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index de9358625b..a7629f7a8e 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -789,7 +789,7 @@ ZEND_FUNCTION(get_class_vars) array_init(return_value); add_class_vars(*pce, &(*pce)->default_properties, return_value TSRMLS_CC); zend_update_class_constants(*pce TSRMLS_CC); - add_class_vars(*pce, (*pce)->static_members, return_value TSRMLS_CC); + add_class_vars(*pce, CE_STATIC_MEMBERS(*pce), return_value TSRMLS_CC); } } /* }}} */ diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 4575392c79..ff20c63625 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2195,7 +2195,7 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro if (parent_ce->type != ce->type) { /* User class extends internal class */ - ht = parent_ce->static_members; + ht = CE_STATIC_MEMBERS(parent_ce); } else { ht = &parent_ce->default_static_members; } @@ -2301,7 +2301,7 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent if (parent_ce->type != ce->type) { /* User class extends internal class */ zend_update_class_constants(parent_ce TSRMLS_CC); - zend_hash_merge(&ce->default_static_members, parent_ce->static_members, (void (*)(void *)) inherit_static_prop, NULL, sizeof(zval *), 0); + zend_hash_merge(&ce->default_static_members, CE_STATIC_MEMBERS(parent_ce), (void (*)(void *)) inherit_static_prop, NULL, sizeof(zval *), 0); } else { zend_hash_merge(&ce->default_static_members, &parent_ce->default_static_members, (void (*)(void *)) inherit_static_prop, NULL, sizeof(zval *), 0); } @@ -4208,7 +4208,23 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify zend_u_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0); zend_u_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, UG(unicode), 0); - ce->static_members = (ce->type == ZEND_INTERNAL_CLASS) ? NULL : &ce->default_static_members; + if (ce->type == ZEND_INTERNAL_CLASS) { +#ifdef ZTS + int n = zend_hash_num_elements(CG(class_table)); + + if (CG(static_members) && n >= CG(last_static_member)) { + /* Support for run-time declaration: dl() */ + CG(last_static_member) = n+1; + CG(static_members) = realloc(CG(static_members), (n+1)*sizeof(HashTable*)); + CG(static_members)[n] = NULL; + } + ce->static_members = (HashTable*)n; +#else + ce->static_members = NULL; +#endif + } else { + ce->static_members = &ce->default_static_members; + } if (nullify_handlers) { ce->constructor = NULL; diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 7900e45268..8de7ed395c 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -143,6 +143,9 @@ struct _zend_compiler_globals { HashTable *global_u_function_table; HashTable *global_u_class_table; HashTable *global_u_auto_globals_table; + + HashTable **static_members; + int last_static_member; #endif }; diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 93e1c27d14..529afee208 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -875,7 +875,7 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, zend_uchar ty zend_update_class_constants(tmp_ce TSRMLS_CC); - zend_u_hash_quick_find(tmp_ce->static_members, UG(unicode)?IS_UNICODE:IS_STRING, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval); + zend_u_hash_quick_find(CE_STATIC_MEMBERS(tmp_ce), UG(unicode)?IS_UNICODE:IS_STRING, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval); if (!retval) { if (silent) { diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index ff46517a74..22f6bc4a8b 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -141,18 +141,20 @@ ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC) ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC) { - if ((*pce)->static_members) { - if ((*pce)->static_members != &(*pce)->default_static_members) { - zend_hash_destroy((*pce)->static_members); - FREE_HASHTABLE((*pce)->static_members); - } - (*pce)->static_members = NULL; - } if ((*pce)->type == ZEND_USER_CLASS) { /* Clean all parts that can contain run-time data */ /* Note that only run-time accessed data need to be cleaned up, pre-defined data can not contain objects and thus are not probelmatic */ zend_hash_apply(&(*pce)->function_table, (apply_func_t) zend_cleanup_function_data TSRMLS_CC); + (*pce)->static_members = NULL; + } else if (CE_STATIC_MEMBERS(*pce)) { + zend_hash_destroy(CE_STATIC_MEMBERS(*pce)); + FREE_HASHTABLE(CE_STATIC_MEMBERS(*pce)); +#ifdef ZTS + CG(static_members)[(long)((*pce)->static_members)] = NULL; +#else + (*pce)->static_members = NULL; +#endif } return 0; } diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index ef1e51ba18..d15f156b63 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -2541,7 +2541,7 @@ ZEND_METHOD(reflection_class, getStaticProperties) zend_update_class_constants(ce TSRMLS_CC); array_init(return_value); - zend_hash_copy(Z_ARRVAL_P(return_value), ce->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); + zend_hash_copy(Z_ARRVAL_P(return_value), CE_STATIC_MEMBERS(ce), (copy_ctor_func_t) zval_add_ref, (void *) &tmp_copy, sizeof(zval *)); } /* }}} */ @@ -3657,7 +3657,7 @@ ZEND_METHOD(reflection_property, getValue) if ((ref->prop->flags & ZEND_ACC_STATIC)) { zend_update_class_constants(intern->ce TSRMLS_CC); - if (zend_u_hash_quick_find(intern->ce->static_members, utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) { + if (zend_u_hash_quick_find(CE_STATIC_MEMBERS(intern->ce), utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) { zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name); /* Bails out */ } @@ -3706,7 +3706,7 @@ ZEND_METHOD(reflection_property, setValue) } } zend_update_class_constants(intern->ce TSRMLS_CC); - prop_table = intern->ce->static_members; + prop_table = CE_STATIC_MEMBERS(intern->ce); } else { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "oz", &object, &value) == FAILURE) { return; diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 2698c3ad12..7407c2e5c1 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -107,6 +107,8 @@ php_basic_globals basic_globals; #include "php_fopen_wrappers.h" #include "streamsfuncs.h" +static zend_class_entry *incomplete_class_entry = NULL; + static ZEND_BEGIN_ARG_INFO(first_and_second__args_force_ref, 0) ZEND_ARG_PASS_INFO(1) @@ -960,7 +962,7 @@ static void basic_globals_ctor(php_basic_globals *basic_globals_p TSRMLS_DC) memset(&BG(mblen_state), 0, sizeof(BG(mblen_state))); #endif - BG(incomplete_class) = php_create_incomplete_class(TSRMLS_C); + BG(incomplete_class) = incomplete_class_entry; } @@ -1026,6 +1028,8 @@ PHP_MINIT_FUNCTION(basic) #endif #endif + BG(incomplete_class) = incomplete_class_entry = php_create_incomplete_class(TSRMLS_C); + REGISTER_LONG_CONSTANT("CONNECTION_ABORTED", PHP_CONNECTION_ABORTED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CONNECTION_NORMAL", PHP_CONNECTION_NORMAL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("CONNECTION_TIMEOUT", PHP_CONNECTION_TIMEOUT, CONST_CS | CONST_PERSISTENT);