]> granicus.if.org Git - php/commitdiff
Fixed bug #34729 (Crash in ZTS mode under Apache)
authorDmitry Stogov <dmitry@php.net>
Thu, 1 Dec 2005 11:48:17 +0000 (11:48 +0000)
committerDmitry Stogov <dmitry@php.net>
Thu, 1 Dec 2005 11:48:17 +0000 (11:48 +0000)
NEWS
Zend/zend.c
Zend/zend_API.c
Zend/zend_API.h
Zend/zend_builtin_functions.c
Zend/zend_compile.c
Zend/zend_globals.h
Zend/zend_object_handlers.c
Zend/zend_opcode.c
ext/reflection/php_reflection.c
ext/standard/basic_functions.c

diff --git a/NEWS b/NEWS
index d6a39529209c697fd33834b3018833cc2323893f..7629acc6747e6a2eb8ee7dabf0a9e5499e0a5177 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -19,6 +19,7 @@ PHP                                                                        NEWS
   connecting to 5.x server. (Andrey)
 - Fixed bug #35496 (Crash in mcrypt_generic()/mdecrypt_generic() without 
   proper init). (Ilia)
+- Fixed bug #34729 (Crash in ZTS mode under Apache). (Dmitry, Zeev) 
 - Fixed bug #35470 (Assigning global using variable name from array doesn't
   function). (Dmitry)
 - Fixed bug #35456 (+ 1 [time unit] format did not work). (Ilia)
index b0150da9930b16566dee81df8ceeb0c2361ade28..f2663e8d5d5b1cb67c0ba27b762783035e18ddc8 100644 (file)
@@ -453,6 +453,13 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS
        compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable));
        zend_hash_init_ex(compiler_globals->auto_globals, 8, NULL, NULL, 1, 0);
        zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, NULL, NULL, sizeof(zend_auto_global) /* empty element */);
+
+       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;
+       }
 }
 
 
@@ -470,6 +477,10 @@ static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS
                zend_hash_destroy(compiler_globals->auto_globals);
                free(compiler_globals->auto_globals);
        }
+       if (compiler_globals->static_members) {
+               free(compiler_globals->static_members);
+       }
+       compiler_globals->last_static_member = 0;
 }
 
 
index d531371ded87479b240753b836d9af1e8c2c55d2..bae16c5492e4a3bcc2da4d73879581dc30a6b572 100644 (file)
@@ -755,22 +755,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_hash_init(class_type->static_members, 0, NULL, ZVAL_PTR_DTOR, 0);
+#endif
+                       zend_hash_init(CE_STATIC_MEMBERS(class_type), 0, NULL, ZVAL_PTR_DTOR, 0);
 
                        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) {
@@ -784,10 +788,10 @@ ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC
                                    class_type->parent &&
                                    zend_hash_find(&class_type->parent->default_static_members, str_index, str_length, (void**)&q) == SUCCESS &&
                                    *p == *q &&
-                                   zend_hash_find(class_type->parent->static_members, str_index, str_length, (void**)&q) == SUCCESS) {
+                                   zend_hash_find(CE_STATIC_MEMBERS(class_type->parent), str_index, str_length, (void**)&q) == SUCCESS) {
                                        (*q)->refcount++;
                                        (*q)->is_ref = 1;
-                                       zend_hash_add(class_type->static_members, str_index, str_length, (void**)q, sizeof(zval*), NULL);
+                                       zend_hash_add(CE_STATIC_MEMBERS(class_type), str_index, str_length, (void**)q, sizeof(zval*), NULL);
                                } else {
                                        zval *q;
                                        
@@ -795,12 +799,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_hash_add(class_type->static_members, str_index, str_length, (void**)&q, sizeof(zval*), NULL);
+                                       zend_hash_add(CE_STATIC_MEMBERS(class_type), 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;
index ef4156430e9f73991c0668b169a3d3d9c9de4e47..d30d7f74996830d5565ecd7ce1b70b49e8797d20 100644 (file)
@@ -146,6 +146,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()
index 61caabc5ed241bae9744c3c7e67883175dd8cc21..5c9917443e9a55def16b98d000bf93a71ee66426 100644 (file)
@@ -738,7 +738,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);
        }
 }
 /* }}} */
index c40b4845e6632a031ff25849aab3b1389f50d98d..f9257698fd98baffaaf61280823b2e3f09643ad8 100644 (file)
@@ -2090,7 +2090,9 @@ 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;
+                                       TSRMLS_FETCH();
+
+                                       ht = CE_STATIC_MEMBERS(parent_ce);
                                } else {
                                        ht = &parent_ce->default_static_members;
                                }
@@ -2196,7 +2198,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);
        }
@@ -4026,7 +4028,23 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
        zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
        zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 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;
index 198b3640c65d01808730b1d9227a81421b85b2cc..80399e59b54d5d54a6d10f40386484ba14e24457 100644 (file)
@@ -144,6 +144,11 @@ struct _zend_compiler_globals {
        zend_encoding_converter encoding_converter;
        zend_encoding_oddlen encoding_oddlen;
 #endif /* ZEND_MULTIBYTE */
+
+#ifdef ZTS
+       HashTable **static_members;
+       int last_static_member;
+#endif
 };
 
 
index a4b80db38b9e535cc1376afcbe5c8dd63348a5b2..4bdcd858b44f66884a3744f96d57b449cb5ea196 100644 (file)
@@ -857,7 +857,7 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert
 
        zend_update_class_constants(tmp_ce TSRMLS_CC);
 
-       zend_hash_quick_find(tmp_ce->static_members, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
+       zend_hash_quick_find(CE_STATIC_MEMBERS(tmp_ce), property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
 
        if (!retval) {
                if (silent) {
index 9b305b25e29df2cfec789326fbc43ffe28dd6a19..a4bf456c125ef027736a2cddc07aaaff9de8c2a3 100644 (file)
@@ -138,18 +138,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;
 }
index a456f38768df6fd765e4f52f910f022625cf646b..5258c4850e0a849a25343080eb474f9dd2e1520a 100644 (file)
@@ -2529,7 +2529,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 *));
 }
 /* }}} */
 
@@ -3633,7 +3633,7 @@ ZEND_METHOD(reflection_property, getValue)
 
        if ((ref->prop->flags & ZEND_ACC_STATIC)) {
                zend_update_class_constants(intern->ce TSRMLS_CC);
-               if (zend_hash_quick_find(intern->ce->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
+               if (zend_hash_quick_find(CE_STATIC_MEMBERS(intern->ce), 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 %s", ref->prop->name);
                        /* Bails out */
                }
@@ -3681,7 +3681,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;
index a4e1ced714b0705c47fdc130cb4fb4a76a300156..be910cf789c29e65af1ec67870d12feec574d4dd 100644 (file)
@@ -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)
@@ -956,7 +958,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;
 }
 
 
@@ -1022,6 +1024,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);