]> granicus.if.org Git - php/commitdiff
fixed craches at request shutdown and memory leaks
authorDmitry Stogov <dmitry@zend.com>
Mon, 31 Mar 2014 12:09:45 +0000 (16:09 +0400)
committerDmitry Stogov <dmitry@zend.com>
Mon, 31 Mar 2014 12:09:45 +0000 (16:09 +0400)
Zend/zend_compile.c
Zend/zend_opcode.c
ext/opcache/ZendAccelerator.c
ext/opcache/zend_accelerator_util_funcs.c
ext/opcache/zend_persist.c
ext/opcache/zend_shared_alloc.c

index 807ebd508e714885eb8958f7bcaa3921c3ad9037..9ba40dfc33b83710739a0633f2290689b87a5177 100644 (file)
@@ -5442,6 +5442,7 @@ void zend_do_declare_property(znode *var_name, const znode *value, zend_uint acc
        Z_STR(var_name->u.constant) = zend_new_interned_string(Z_STR(var_name->u.constant) TSRMLS_CC);
        zend_declare_property_ex(CG(active_class_entry), Z_STR(var_name->u.constant), &property, access_type, comment TSRMLS_CC);
 //???  efree(Z_STRVAL(var_name->u.constant));
+       STR_RELEASE(Z_STR(var_name->u.constant));
 }
 /* }}} */
 
index 039c3bbd7646cd79ceebe161708b6db59c578e17..08108d283f135583f5b5202b39395a5427456e5d 100644 (file)
@@ -115,6 +115,9 @@ ZEND_API void destroy_zend_function(zend_function *function TSRMLS_DC)
                        destroy_op_array((zend_op_array *) function TSRMLS_CC);
                        break;
                case ZEND_INTERNAL_FUNCTION:
+                       if (function->common.function_name) {
+                               STR_RELEASE(function->common.function_name);
+                       }
                        /* do nothing */
                        break;
        }
index 85347be976c1af6618b72ec44a3aef08e83da21e..5df02c98c84967216ec8d43aa9230fc8ed4fc006 100644 (file)
@@ -2524,9 +2524,14 @@ static void accel_globals_ctor(zend_accel_globals *accel_globals TSRMLS_DC)
        zend_accel_copy_internal_functions(TSRMLS_C);
 }
 
+static void accel_globals_internal_func_dtor(zval *zv)
+{
+       free(Z_PTR_P(zv));
+}
+
 static void accel_globals_dtor(zend_accel_globals *accel_globals TSRMLS_DC)
 {
-       accel_globals->function_table.pDestructor = NULL;
+       accel_globals->function_table.pDestructor = accel_globals_internal_func_dtor;
        zend_hash_destroy(&accel_globals->function_table);
 }
 
@@ -2724,6 +2729,7 @@ void accel_shutdown(TSRMLS_D)
 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
        if (ZCG(accel_directives).interned_strings_buffer) {
 # ifndef ZTS
+               zend_hash_clean(CG(auto_globals));
                zend_hash_clean(CG(function_table));
                zend_hash_clean(CG(class_table));
                zend_hash_clean(EG(zend_constants));
index 3769e362fe3075ac14add2b5130766d25c5d41b0..1ea652bc46a3fad1b8e09663c5ad4d74d2115dc6 100644 (file)
@@ -49,8 +49,9 @@ static int zend_prepare_function_for_execution(zend_op_array *op_array);
 static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind);
 static zend_ast *zend_ast_clone(zend_ast *ast TSRMLS_DC);
 
-static void zend_accel_destroy_zend_function(zend_function *function)
+static void zend_accel_destroy_zend_function(zval *zv)
 {
+       zend_function *function = Z_PTR_P(zv);
        TSRMLS_FETCH();
 
        if (function->type == ZEND_USER_FUNCTION) {
@@ -67,7 +68,7 @@ static void zend_accel_destroy_zend_function(zend_function *function)
 static void zend_accel_destroy_zend_class(zval *zv)
 {
        zend_class_entry *ce = Z_PTR_P(zv);
-       ce->function_table.pDestructor = (dtor_func_t) zend_accel_destroy_zend_function;
+       ce->function_table.pDestructor = zend_accel_destroy_zend_function;
        destroy_zend_class(zv);
 }
 
@@ -150,8 +151,8 @@ int compact_persistent_script(zend_persistent_script *persistent_script)
 void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements)
 {
        if (destroy_elements) {
-               persistent_script->function_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_function;
-               persistent_script->class_table.pDestructor = (dtor_func_t)zend_accel_destroy_zend_class;
+               persistent_script->function_table.pDestructor = zend_accel_destroy_zend_function;
+               persistent_script->class_table.pDestructor = zend_accel_destroy_zend_class;
        } else {
                persistent_script->function_table.pDestructor = NULL;
                persistent_script->class_table.pDestructor = NULL;
@@ -196,7 +197,8 @@ static int move_user_function(zval *zv
 #endif 
 
        if (function->type == ZEND_USER_FUNCTION) {
-               zend_hash_update_mem(function_table, hash_key->key, function, sizeof(zend_function));
+               zend_hash_update_ptr(function_table, hash_key->key, function);
+//???          zend_hash_update_mem(function_table, hash_key->key, function, sizeof(zend_function));
                return 1;
        } else {
                return 0;
@@ -231,12 +233,15 @@ void zend_accel_copy_internal_functions(TSRMLS_D)
        ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table));
 }
 
-static void zend_destroy_property_info(zend_property_info *property_info)
+static void zend_destroy_property_info(zval *zv)
 {
+       zend_property_info *property_info = Z_PTR_P(zv);
+
        STR_RELEASE(property_info->name);
        if (property_info->doc_comment) {
                STR_RELEASE(property_info->doc_comment);
        }
+       efree(property_info);
 }
 
 static inline void zend_clone_zval(zval *src, int bind TSRMLS_DC)
@@ -250,15 +255,17 @@ static inline void zend_clone_zval(zval *src, int bind TSRMLS_DC)
 #endif
                case IS_STRING:
            case IS_CONSTANT:
-               if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_STR_P(src))) != NULL) {
-                       Z_STR_P(src) = ptr;
-                       } else {
-                               zend_string *old = Z_STR_P(src);
+                       if (!IS_INTERNED(Z_STR_P(src))) {
+                               if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_STR_P(src))) != NULL) {
+                                       Z_STR_P(src) = ptr;
+                               } else {
+                                       zend_string *old = Z_STR_P(src);
 
-                               Z_STR_P(src) = STR_DUP(old, 0);
-                               Z_STR_P(src)->gc = old->gc;
-                       if (bind && Z_REFCOUNT_P(src) > 1) {
-                                       accel_xlat_set(old, Z_STR_P(src));
+                                       Z_STR_P(src) = STR_DUP(old, 0);
+                                       Z_STR_P(src)->gc = old->gc;
+                                       if (bind && Z_REFCOUNT_P(src) > 1) {
+                                               accel_xlat_set(old, Z_STR_P(src));
+                                       }
                                }
                        }
                        break;
@@ -513,7 +520,7 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla
        ht->nNumUsed = 0;
        ht->nNumOfElements = source->nNumOfElements;
        ht->nNextFreeElement = source->nNextFreeElement;
-       ht->pDestructor = (dtor_func_t) zend_destroy_property_info;
+       ht->pDestructor = zend_destroy_property_info;
 #if ZEND_DEBUG
 //???  ht->inconsistent = 0;
 #endif
@@ -801,15 +808,17 @@ static int zend_hash_unique_copy_mem(HashTable *target, HashTable *source, uniqu
 {
        uint idx;
        Bucket *p;
-       void *t;
+       zval *t;
 
        for (idx = 0; idx < source->nNumUsed; idx++) {          
                p = source->arData + idx;
                if (Z_TYPE(p->val) == IS_UNDEF) continue;
                if (p->key) {
-                       if ((t = zend_hash_add_mem(target, p->key, Z_PTR(p->val), size)) != NULL) {
+                       if ((t = zend_hash_add(target, p->key, &p->val)) != NULL) {
+                               Z_PTR_P(t) = emalloc(size);
+                               memcpy(Z_PTR_P(t), Z_PTR(p->val), size);
                                if (pCopyConstructor) {
-                                       pCopyConstructor(t);
+                                       pCopyConstructor(Z_PTR_P(t));
                                }
                        } else {
                                if (p->key->len > 0 && p->key->val[0] == 0) {
@@ -817,29 +826,33 @@ static int zend_hash_unique_copy_mem(HashTable *target, HashTable *source, uniqu
 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
                                        if (((zend_function*)Z_PTR(p->val))->common.fn_flags & ZEND_ACC_CLOSURE) {
                                                /* update closure */
-                                               if ((t = zend_hash_update_mem(target, p->key, Z_PTR(p->val), size)) != NULL) {
+                                               if ((t = zend_hash_update(target, p->key, &p->val)) != NULL) {
+                                                       Z_PTR_P(t) = emalloc(size);
+                                                       memcpy(Z_PTR_P(t), Z_PTR(p->val), size);
                                                        if (pCopyConstructor) {
-                                                               pCopyConstructor(t);
+                                                               pCopyConstructor(Z_PTR_P(t));
                                                        }
                                                }
                                        } else {
                                                /* ignore and wait for runtime */
                                        } 
 #endif
-                               } else if (!ignore_dups && (t = zend_hash_find_ptr(target, p->key)) != NULL) {
+                               } else if (!ignore_dups && (t = zend_hash_find(target, p->key)) != NULL) {
                                        *fail_data = Z_PTR(p->val);
-                                       *conflict_data = t;
+                                       *conflict_data = Z_PTR_P(t);
                                        return FAILURE;
                                }
                        }
                } else {
-                       if (!zend_hash_index_exists(target, p->h) && (t = zend_hash_index_update_mem(target, p->h, Z_PTR(p->val), size)) != NULL) {
+                       if (!zend_hash_index_exists(target, p->h) && (t = zend_hash_index_update(target, p->h, &p->val)) != NULL) {
+                               Z_PTR_P(t) = emalloc(size);
+                               memcpy(Z_PTR_P(t), Z_PTR(p->val), size);
                                if (pCopyConstructor) {
-                                       pCopyConstructor(t);
+                                       pCopyConstructor(Z_PTR_P(t));
                                }
-                       } else if (!ignore_dups && (t = zend_hash_index_find_ptr(target,p->h)) != NULL) {
+                       } else if (!ignore_dups && (t = zend_hash_index_find(target,p->h)) != NULL) {
                                *fail_data = Z_PTR(p->val);
-                               *conflict_data = t;
+                               *conflict_data = Z_PTR_P(t);
                                return FAILURE;
                        }
                }
index cfac1960a2b2de7f2d7750af6064ac237a439bde..13287025bb5ddf22f6c54fe53364d677dbc25d2c 100644 (file)
@@ -186,7 +186,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
 
        if (op_array->filename) {
                /* do not free! PHP has centralized filename storage, compiler will free it */
-               zend_accel_memdup_string(op_array->filename);
+               op_array->filename = zend_accel_memdup_string(op_array->filename);
        }
 
        if (main_persistent_script) {
@@ -354,9 +354,13 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
                        for (i = 0; i < op_array->num_args; i++) {
                                if (op_array->arg_info[i].name) {
 //???                                  zend_accel_store_interned_string(op_array->arg_info[i].name, op_array->arg_info[i].name_len + 1);
+                                       efree(op_array->arg_info[i].name);
+                                       op_array->arg_info[i].name = NULL;
                                }
                                if (op_array->arg_info[i].class_name) {
 //???                                  zend_accel_store_interned_string(op_array->arg_info[i].class_name, op_array->arg_info[i].class_name_len + 1);
+                                       efree(op_array->arg_info[i].class_name);
+                                       op_array->arg_info[i].class_name = NULL;
                                }
                        }
                }
@@ -476,7 +480,7 @@ static void zend_persist_class_entry(zval *zv TSRMLS_DC)
 
                if (ZEND_CE_FILENAME(ce)) {
                        /* do not free! PHP has centralized filename storage, compiler will free it */
-                       zend_accel_memdup_string(ZEND_CE_FILENAME(ce));
+                       ZEND_CE_FILENAME(ce) = zend_accel_memdup_string(ZEND_CE_FILENAME(ce));
                }
                if (ZEND_CE_DOC_COMMENT(ce)) {
                        if (ZCG(accel_directives).save_comments) {
index 061a4e2777b34f1739c2006035f03b4549ab3d65..73f331de6f2fc4232b1b8296b5bac717ed069672 100644 (file)
@@ -347,6 +347,7 @@ void *_zend_shared_memdup(void *source, size_t size, zend_bool free_source TSRML
        ZCG(mem) = (void*)(((char*)ZCG(mem)) + ZEND_ALIGNED_SIZE(size));
        memcpy(retval, source, size);
        if (free_source) {
+               efree(source);
 //???          interned_efree((char*)source);
        }
        zend_shared_alloc_register_xlat_entry(source, retval);