Fixed memory leak

This commit is contained in:
Dmitry Stogov 2015-02-20 20:50:01 +03:00
parent 09ac3e931c
commit e142e31137
2 changed files with 61 additions and 5 deletions

View 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));

View File

@ -230,6 +230,63 @@ static void zend_persist_zval(zval *z)
}
}
static void zend_persist_zval_static(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_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;
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));
Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_IMMUTABLE;
GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
}
break;
}
}
static void zend_persist_zval_const(zval *z)
{
zend_uchar flags;
@ -280,8 +337,6 @@ static void zend_persist_zval_const(zval *z)
} else {
zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_IMMUTABLE;
GC_REFCOUNT(Z_COUNTED_P(z)) = 2;
}
break;
}
@ -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;