colder Mon, 10 Aug 2009 15:18:13 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=287043
Log: Fix endless recursion of var_dump() over self-referencing closures Changed paths: A php/php-src/branches/PHP_5_3/Zend/tests/closure_034.phpt U php/php-src/branches/PHP_5_3/Zend/zend_closures.c A php/php-src/trunk/Zend/tests/closure_034.phpt U php/php-src/trunk/Zend/zend_closures.c
Added: php/php-src/branches/PHP_5_3/Zend/tests/closure_034.phpt =================================================================== --- php/php-src/branches/PHP_5_3/Zend/tests/closure_034.phpt (rev 0) +++ php/php-src/branches/PHP_5_3/Zend/tests/closure_034.phpt 2009-08-10 15:18:13 UTC (rev 287043) @@ -0,0 +1,25 @@ +--TEST-- +Closure 033: Recursive var_dump on closures +--FILE-- +<?php + +$a = function () use(&$a) {}; +var_dump($a); + +?> +===DONE=== +--EXPECTF-- +object(Closure)#1 (1) { + ["static"]=> + array(1) { + ["a"]=> + &object(Closure)#1 (1) { + ["static"]=> + array(1) { + ["a"]=> + *RECURSION* + } + } + } +} +===DONE=== Modified: php/php-src/branches/PHP_5_3/Zend/zend_closures.c =================================================================== --- php/php-src/branches/PHP_5_3/Zend/zend_closures.c 2009-08-10 14:01:03 UTC (rev 287042) +++ php/php-src/branches/PHP_5_3/Zend/zend_closures.c 2009-08-10 15:18:13 UTC (rev 287043) @@ -37,6 +37,7 @@ typedef struct _zend_closure { zend_object std; zend_function func; + HashTable *debug_info; } zend_closure; /* non-static since it needs to be referenced */ @@ -179,6 +180,11 @@ destroy_op_array(&closure->func.op_array TSRMLS_CC); } + if (closure->debug_info != NULL) { + zend_hash_destroy(closure->debug_info); + efree(closure->debug_info); + } + efree(closure); } /* }}} */ @@ -222,48 +228,53 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */ { zend_closure *closure = (zend_closure *)zend_object_store_get_object(object TSRMLS_CC); - HashTable *rv; zval *val; struct _zend_arg_info *arg_info = closure->func.common.arg_info; - *is_temp = 1; - ALLOC_HASHTABLE(rv); - zend_hash_init(rv, 1, NULL, ZVAL_PTR_DTOR, 0); - if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) { - HashTable *static_variables = closure->func.op_array.static_variables; - MAKE_STD_ZVAL(val); - array_init(val); - zend_hash_copy(Z_ARRVAL_P(val), static_variables, (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval*)); - zend_symtable_update(rv, "static", sizeof("static"), (void *) &val, sizeof(zval *), NULL); + *is_temp = 0; + + if (closure->debug_info == NULL) { + ALLOC_HASHTABLE(closure->debug_info); + zend_hash_init(closure->debug_info, 1, NULL, ZVAL_PTR_DTOR, 0); } + if (closure->debug_info->nApplyCount == 0) { + if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) { + HashTable *static_variables = closure->func.op_array.static_variables; + MAKE_STD_ZVAL(val); + array_init(val); + zend_hash_copy(Z_ARRVAL_P(val), static_variables, (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval*)); + zend_symtable_update(closure->debug_info, "static", sizeof("static"), (void *) &val, sizeof(zval *), NULL); + } - if (arg_info) { - zend_uint i, required = closure->func.common.required_num_args; + if (arg_info) { + zend_uint i, required = closure->func.common.required_num_args; - MAKE_STD_ZVAL(val); - array_init(val); + MAKE_STD_ZVAL(val); + array_init(val); - for (i = 0; i < closure->func.common.num_args; i++) { - char *name, *info; - int name_len, info_len; - if (arg_info->name) { - name_len = zend_spprintf(&name, 0, "%s$%s", - arg_info->pass_by_reference ? "&" : "", - arg_info->name); - } else { - name_len = zend_spprintf(&name, 0, "%s$param%d", - arg_info->pass_by_reference ? "&" : "", - i + 1); + for (i = 0; i < closure->func.common.num_args; i++) { + char *name, *info; + int name_len, info_len; + if (arg_info->name) { + name_len = zend_spprintf(&name, 0, "%s$%s", + arg_info->pass_by_reference ? "&" : "", + arg_info->name); + } else { + name_len = zend_spprintf(&name, 0, "%s$param%d", + arg_info->pass_by_reference ? "&" : "", + i + 1); + } + info_len = zend_spprintf(&info, 0, "%s", + i >= required ? "<optional>" : "<required>"); + add_assoc_stringl_ex(val, name, name_len + 1, info, info_len, 0); + efree(name); + arg_info++; } - info_len = zend_spprintf(&info, 0, "%s", - i >= required ? "<optional>" : "<required>"); - add_assoc_stringl_ex(val, name, name_len + 1, info, info_len, 0); - efree(name); - arg_info++; + zend_symtable_update(closure->debug_info, "parameter", sizeof("parameter"), (void *) &val, sizeof(zval *), NULL); } - zend_symtable_update(rv, "parameter", sizeof("parameter"), (void *) &val, sizeof(zval *), NULL); } - return rv; + + return closure->debug_info; } /* }}} */ Added: php/php-src/trunk/Zend/tests/closure_034.phpt =================================================================== --- php/php-src/trunk/Zend/tests/closure_034.phpt (rev 0) +++ php/php-src/trunk/Zend/tests/closure_034.phpt 2009-08-10 15:18:13 UTC (rev 287043) @@ -0,0 +1,29 @@ +--TEST-- +Closure 033: Recursive var_dump on closures +--FILE-- +<?php + +$a = function () use(&$a) {}; +var_dump($a); + +?> +===DONE=== +--EXPECTF-- +object(Closure)#1 (2) { + ["this"]=> + NULL + ["static"]=> + array(1) { + [u"a"]=> + &object(Closure)#1 (2) { + ["this"]=> + NULL + ["static"]=> + array(1) { + [u"a"]=> + *RECURSION* + } + } + } +} +===DONE=== Modified: php/php-src/trunk/Zend/zend_closures.c =================================================================== --- php/php-src/trunk/Zend/zend_closures.c 2009-08-10 14:01:03 UTC (rev 287042) +++ php/php-src/trunk/Zend/zend_closures.c 2009-08-10 15:18:13 UTC (rev 287043) @@ -38,6 +38,7 @@ zend_object std; zend_function func; zval *this_ptr; + HashTable *debug_info; } zend_closure; /* non-static since it needs to be referenced */ @@ -192,6 +193,11 @@ zval_ptr_dtor(&closure->this_ptr); } + if (closure->debug_info != NULL) { + zend_hash_destroy(closure->debug_info); + efree(closure->debug_info); + } + efree(closure); } /* }}} */ @@ -242,55 +248,60 @@ static HashTable *zend_closure_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */ { zend_closure *closure = (zend_closure *)zend_object_store_get_object(object TSRMLS_CC); - HashTable *rv; zval *val; struct _zend_arg_info *arg_info = closure->func.common.arg_info; - *is_temp = 1; - ALLOC_HASHTABLE(rv); - zend_hash_init(rv, 1, NULL, ZVAL_PTR_DTOR, 0); - val = closure->this_ptr; - if (!val) { - ALLOC_INIT_ZVAL(val); - } else { - Z_ADDREF_P(val); + *is_temp = 0; + + if (closure->debug_info == NULL) { + ALLOC_HASHTABLE(closure->debug_info); + zend_hash_init(closure->debug_info, 1, NULL, ZVAL_PTR_DTOR, 0); } - zend_symtable_update(rv, "this", sizeof("this"), (void *) &val, sizeof(zval *), NULL); - if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) { - HashTable *static_variables = closure->func.op_array.static_variables; - MAKE_STD_ZVAL(val); - array_init(val); - zend_hash_copy(Z_ARRVAL_P(val), static_variables, (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval*)); - zend_symtable_update(rv, "static", sizeof("static"), (void *) &val, sizeof(zval *), NULL); - } - if (arg_info) { - zend_uint i, required = closure->func.common.required_num_args; + if (closure->debug_info->nApplyCount == 0) { + val = closure->this_ptr; + if (!val) { + ALLOC_INIT_ZVAL(val); + } else { + Z_ADDREF_P(val); + } + zend_symtable_update(closure->debug_info, "this", sizeof("this"), (void *) &val, sizeof(zval *), NULL); + if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) { + HashTable *static_variables = closure->func.op_array.static_variables; + MAKE_STD_ZVAL(val); + array_init(val); + zend_hash_copy(Z_ARRVAL_P(val), static_variables, (copy_ctor_func_t)zval_add_ref, NULL, sizeof(zval*)); + zend_symtable_update(closure->debug_info, "static", sizeof("static"), (void *) &val, sizeof(zval *), NULL); + } - MAKE_STD_ZVAL(val); - array_init(val); + if (arg_info) { + zend_uint i, required = closure->func.common.required_num_args; - for (i = 0; i < closure->func.common.num_args; i++) { - char *name, *info; - int name_len, info_len; - if (arg_info->name.v) { - name_len = zend_spprintf(&name, 0, "%s$%v", - arg_info->pass_by_reference ? "&" : "", - arg_info->name.v); - } else { - name_len = zend_spprintf(&name, 0, "%s$param%d", - arg_info->pass_by_reference ? "&" : "", - i + 1); + MAKE_STD_ZVAL(val); + array_init(val); + + for (i = 0; i < closure->func.common.num_args; i++) { + char *name, *info; + int name_len, info_len; + if (arg_info->name.v) { + name_len = zend_spprintf(&name, 0, "%s$%v", + arg_info->pass_by_reference ? "&" : "", + arg_info->name.v); + } else { + name_len = zend_spprintf(&name, 0, "%s$param%d", + arg_info->pass_by_reference ? "&" : "", + i + 1); + } + info_len = zend_spprintf(&info, 0, "%s", + i >= required ? "<optional>" : "<required>"); + add_assoc_stringl_ex(val, name, name_len + 1, info, info_len, 0); + efree(name); + arg_info++; } - info_len = zend_spprintf(&info, 0, "%s", - i >= required ? "<optional>" : "<required>"); - add_assoc_stringl_ex(val, name, name_len + 1, info, info_len, 0); - efree(name); - arg_info++; + zend_symtable_update(closure->debug_info, "parameter", sizeof("parameter"), (void *) &val, sizeof(zval *), NULL); } - zend_symtable_update(rv, "parameter", sizeof("parameter"), (void *) &val, sizeof(zval *), NULL); } - return rv; + return closure->debug_info; } /* }}} */
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php