]> granicus.if.org Git - php/commitdiff
Fixed memory leak
authorDmitry Stogov <dmitry@zend.com>
Fri, 20 Feb 2015 17:50:01 +0000 (20:50 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 20 Feb 2015 17:50:01 +0000 (20:50 +0300)
Zend/zend_execute_API.c
ext/opcache/zend_persist.c

index 0d722e5820d34ade19441ffd77f08e9046f778e8..fc94beeb7fc5b284c0a209bb7709e498d0d6441a 100644 (file)
@@ -595,8 +595,9 @@ ZEND_API int zval_update_constant_ex(zval *p, zend_bool inline_change, zend_clas
                if (Z_REFCOUNTED_P(p)) Z_SET_REFCOUNT_P(p, refcount);
        } else if (Z_TYPE_P(p) == IS_CONSTANT_AST) {
                zval tmp;
-               SEPARATE_ZVAL_NOREF(p);
-
+               if (inline_change) {
+                       SEPARATE_ZVAL_NOREF(p);
+               }
                zend_ast_evaluate(&tmp, Z_ASTVAL_P(p), scope);
                if (inline_change) {
                        zend_ast_destroy_and_free(Z_ASTVAL_P(p));
index eb442e97428696537bc1947e296c3a81dd5014df..9a929be6abdb7d5c4aab2d9e5ae1cfc2b5e9e02d 100644 (file)
@@ -230,7 +230,7 @@ static void zend_persist_zval(zval *z)
        }
 }
 
-static void zend_persist_zval_const(zval *z)
+static void zend_persist_zval_static(zval *z)
 {
        zend_uchar flags;
        void *new_ptr;
@@ -239,7 +239,7 @@ static void zend_persist_zval_const(zval *z)
                case IS_STRING:
                case IS_CONSTANT:
                        flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
-                       zend_accel_memdup_interned_string(Z_STR_P(z));
+                       zend_accel_store_interned_string(Z_STR_P(z));
                        Z_GC_FLAGS_P(z) |= flags;
                        Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
                        break;
@@ -287,6 +287,61 @@ static void zend_persist_zval_const(zval *z)
        }
 }
 
+static void zend_persist_zval_const(zval *z)
+{
+       zend_uchar flags;
+       void *new_ptr;
+
+       switch (Z_TYPE_P(z)) {
+               case IS_STRING:
+               case IS_CONSTANT:
+                       flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
+                       zend_accel_memdup_interned_string(Z_STR_P(z));
+                       Z_GC_FLAGS_P(z) |= flags;
+                       Z_TYPE_FLAGS_P(z) &= ~(IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
+                       break;
+               case IS_ARRAY:
+                       new_ptr = zend_shared_alloc_get_xlat_entry(Z_ARR_P(z));
+                       if (new_ptr) {
+                               Z_ARR_P(z) = new_ptr;
+                               Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
+                       } else {
+                               if (Z_IMMUTABLE_P(z)) {
+                                       Z_ARR_P(z) = zend_accel_memdup(Z_ARR_P(z), sizeof(zend_array));
+                                       zend_hash_persist_immutable(Z_ARRVAL_P(z));
+                               } else {
+                                       GC_REMOVE_FROM_BUFFER(Z_ARR_P(z));
+                                       zend_accel_store(Z_ARR_P(z), sizeof(zend_array));
+                                       zend_hash_persist(Z_ARRVAL_P(z), zend_persist_zval);
+                                       /* make immutable array */
+                                       Z_TYPE_FLAGS_P(z) = IS_TYPE_IMMUTABLE;
+                                       GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
+                                       GC_FLAGS(Z_COUNTED_P(z)) |= IS_ARRAY_IMMUTABLE;
+                                       Z_ARRVAL_P(z)->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
+                               }
+                       }
+                       break;
+               case IS_REFERENCE:
+                       new_ptr = zend_shared_alloc_get_xlat_entry(Z_REF_P(z));
+                       if (new_ptr) {
+                               Z_REF_P(z) = new_ptr;
+                       } else {
+                               zend_accel_store(Z_REF_P(z), sizeof(zend_reference));
+                               zend_persist_zval(Z_REFVAL_P(z));
+                       }
+                       break;
+               case IS_CONSTANT_AST:
+                       new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
+                       if (new_ptr) {
+                               Z_AST_P(z) = new_ptr;
+                       } else {
+                               zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
+                               Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
+                       }
+                       break;
+       }
+}
+
 static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_script* main_persistent_script)
 {
        int already_stored = 0;
@@ -322,7 +377,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
                if (stored) {
                        op_array->static_variables = stored;
                } else {
-                       zend_hash_persist(op_array->static_variables, zend_persist_zval_const);
+                       zend_hash_persist(op_array->static_variables, zend_persist_zval_static);
                        zend_accel_store(op_array->static_variables, sizeof(HashTable));
                        /* make immutable array */
                        GC_REFCOUNT(op_array->static_variables) = 2;