Skip to content

Commit 6c0508f

Browse files
committed
Fixed bug #62907 (Double free when use traits)
1 parent ff0aa24 commit 6c0508f

File tree

5 files changed

+20
-6
lines changed

5 files changed

+20
-6
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ PHP NEWS
99
some builtin classes). (Laruence)
1010
. Fixed bug #62955 (Only one directive is loaded from "Per Directory Values"
1111
Windows registry). (aserbulov at parallels dot com)
12+
. Fixed bug #62907 (Double free when use traits). (Dmitry)
1213

1314
- SOAP
1415
. Fixed bug #50997 (SOAP Error when trying to submit 2nd Element of a choice).

Zend/tests/bug62907.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
--TEST--
22
Bug #62907 (Double free when use traits)
3-
--XFAIL--
4-
bug is not fixed yet
53
--FILE--
64
<?php
75
function __autoload($name) {

Zend/zend_compile.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3878,10 +3878,10 @@ static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args,
38783878
&& (zend_binary_strcasecmp(aliases[i]->trait_method->method_name, aliases[i]->trait_method->mname_len, fn->common.function_name, fnname_len) == 0)) {
38793879
fn_copy = *fn;
38803880
function_add_ref(&fn_copy);
3881-
/* this function_name is never destroyed, because its refcount
3882-
greater than 1 and classes are always destoyed before the
3883-
traits they use */
3881+
/* this function_name is never destroyed, because ZEND_ACC_ALIAS
3882+
flag is set */
38843883
fn_copy.common.function_name = aliases[i]->alias;
3884+
fn_copy.common.fn_flags |= ZEND_ACC_ALIAS;
38853885

38863886
/* if it is 0, no modifieres has been changed */
38873887
if (aliases[i]->modifiers) {
@@ -3914,6 +3914,7 @@ static int zend_traits_copy_functions(zend_function *fn TSRMLS_DC, int num_args,
39143914
/* is not in hashtable, thus, function is not to be excluded */
39153915
fn_copy = *fn;
39163916
function_add_ref(&fn_copy);
3917+
fn_copy.common.fn_flags |= ZEND_ACC_ALIAS;
39173918

39183919
/* apply aliases which are not qualified by a class name, or which have not
39193920
* alias name, just setting visibility */

Zend/zend_compile.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,8 @@ typedef struct _zend_try_catch_element {
207207
#define ZEND_ACC_RETURN_REFERENCE 0x4000000
208208
#define ZEND_ACC_DONE_PASS_TWO 0x8000000
209209

210+
#define ZEND_ACC_ALIAS 0x10000000
211+
210212
char *zend_visibility_string(zend_uint fn_flags);
211213

212214

Zend/zend_opcode.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,15 @@ void _destroy_zend_class_traits_info(zend_class_entry *ce)
267267
}
268268
}
269269

270+
static int zend_clear_trait_method_name(zend_op_array *op_array TSRMLS_DC)
271+
{
272+
if (op_array->function_name && (op_array->fn_flags & ZEND_ACC_ALIAS) == 0) {
273+
efree(op_array->function_name);
274+
op_array->function_name = NULL;
275+
}
276+
return 0;
277+
}
278+
270279
ZEND_API void destroy_zend_class(zend_class_entry **pce)
271280
{
272281
zend_class_entry *ce = *pce;
@@ -298,6 +307,9 @@ ZEND_API void destroy_zend_class(zend_class_entry **pce)
298307
}
299308
zend_hash_destroy(&ce->properties_info);
300309
str_efree(ce->name);
310+
if ((ce->ce_flags & ZEND_ACC_TRAIT) == ZEND_ACC_TRAIT) {
311+
zend_hash_apply(&ce->function_table, (apply_func_t)zend_clear_trait_method_name TSRMLS_CC);
312+
}
301313
zend_hash_destroy(&ce->function_table);
302314
zend_hash_destroy(&ce->constants_table);
303315
if (ce->num_interfaces > 0 && ce->interfaces) {
@@ -387,7 +399,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC)
387399
}
388400
efree(op_array->opcodes);
389401

390-
if (op_array->function_name) {
402+
if (op_array->function_name && (op_array->fn_flags & ZEND_ACC_ALIAS) == 0) {
391403
efree((char*)op_array->function_name);
392404
}
393405
if (op_array->doc_comment) {

0 commit comments

Comments
 (0)