From 3edad871be1e22a99d55efadb4467030b353b213 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 11 Aug 2022 22:36:34 +0200 Subject: [PATCH] Show function name when dumping fake closure Fixes GH-8962 --- Zend/tests/bug75290.phpt | 4 +- .../first_class_callable_optimization.phpt | 8 +++- Zend/tests/gh8083.phpt | 4 +- Zend/tests/gh8962.phpt | 40 +++++++++++++++++++ Zend/zend_closures.c | 16 ++++++++ 5 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 Zend/tests/gh8962.phpt diff --git a/Zend/tests/bug75290.phpt b/Zend/tests/bug75290.phpt index 9d9d1a05619c1..948a56e172a14 100644 --- a/Zend/tests/bug75290.phpt +++ b/Zend/tests/bug75290.phpt @@ -9,7 +9,9 @@ var_dump(function ($someThing) {}); ?> --EXPECT-- -object(Closure)#2 (1) { +object(Closure)#2 (2) { + ["function"]=> + string(3) "sin" ["parameter"]=> array(1) { ["$num"]=> diff --git a/Zend/tests/first_class_callable_optimization.phpt b/Zend/tests/first_class_callable_optimization.phpt index 22ced0a8176c2..707b6a7299a4a 100644 --- a/Zend/tests/first_class_callable_optimization.phpt +++ b/Zend/tests/first_class_callable_optimization.phpt @@ -11,7 +11,11 @@ var_dump(test2(...)); ?> --EXPECT-- -object(Closure)#1 (0) { +object(Closure)#1 (1) { + ["function"]=> + string(5) "test1" } -object(Closure)#1 (0) { +object(Closure)#1 (1) { + ["function"]=> + string(5) "test2" } diff --git a/Zend/tests/gh8083.phpt b/Zend/tests/gh8083.phpt index a98de47cbf375..b3bcfa4579130 100644 --- a/Zend/tests/gh8083.phpt +++ b/Zend/tests/gh8083.phpt @@ -13,7 +13,9 @@ var_dump($x); ?> --EXPECT-- -object(Closure)#1 (1) { +object(Closure)#1 (2) { + ["function"]=> + string(4) "func" ["static"]=> array(1) { ["i"]=> diff --git a/Zend/tests/gh8962.phpt b/Zend/tests/gh8962.phpt new file mode 100644 index 0000000000000..ea963e1958a95 --- /dev/null +++ b/Zend/tests/gh8962.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-8962: Display function name when var_dumping fake closure +--FILE-- + +--EXPECT-- +object(Closure)#2 (2) { + ["function"]=> + string(12) "Foo\Bar::baz" + ["this"]=> + object(Foo\Bar)#1 (0) { + } +} +object(Closure)#2 (1) { + ["function"]=> + string(12) "Foo\Bar::qux" +} +object(Closure)#2 (1) { + ["function"]=> + string(12) "Foo\Bar::qux" +} +object(Closure)#2 (1) { + ["function"]=> + string(8) "Foo\quux" +} diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 3a2c3b11d385c..f697f25a0f802 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -568,6 +568,22 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) debug_info = zend_new_array(8); + if (closure->func.op_array.fn_flags & ZEND_ACC_FAKE_CLOSURE) { + if (closure->func.common.scope) { + zend_string *class_name = closure->func.common.scope->name; + zend_string *func_name = closure->func.common.function_name; + zend_string *combined = zend_string_concat3( + ZSTR_VAL(class_name), ZSTR_LEN(class_name), + "::", strlen("::"), + ZSTR_VAL(func_name), ZSTR_LEN(func_name) + ); + ZVAL_STR(&val, combined); + } else { + ZVAL_STR_COPY(&val, closure->func.common.function_name); + } + zend_hash_update(debug_info, ZSTR_KNOWN(ZEND_STR_FUNCTION), &val); + } + if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) { zval *var; zend_string *key;