From: Dmitry Stogov Date: Fri, 20 Feb 2015 17:50:01 +0000 (+0300) Subject: Fixed memory leak X-Git-Tag: PRE_PHP7_EREG_MYSQL_REMOVALS~96 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e142e31137a85885f0cec83fe0aab1874846a077;p=php Fixed memory leak --- diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 0d722e5820..fc94beeb7f 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -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)); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index eb442e9742..9a929be6ab 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -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;