From 213063f6ca0780ea5adf07467a826b348f29b79a Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 24 May 2021 07:26:56 +0200 Subject: [PATCH] Fix #81076 Invalid implicit binds cause incorrect count in static vars of closure debug info --- NEWS | 4 ++++ Zend/tests/bug81076.phpt | 9 +++++++++ Zend/zend_closures.c | 29 ++++++++++++++++++++++------- 3 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 Zend/tests/bug81076.phpt diff --git a/NEWS b/NEWS index 1e97f1dd876..bdf5dd448d5 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2021, PHP 8.0.8 +- Core: + . Fixed bug #81076 (incorrect debug info on Closures with implicit binds). + (krakjoe) + - Opcache: . Fixed bug #80968 (JIT segfault with return from required file). (Dmitry) diff --git a/Zend/tests/bug81076.phpt b/Zend/tests/bug81076.phpt new file mode 100644 index 00000000000..27d5d8d10f1 --- /dev/null +++ b/Zend/tests/bug81076.phpt @@ -0,0 +1,9 @@ +--TEST-- +Bug #81076 Invalid implicit binds cause incorrect static var count in closure debug info +--FILE-- + [$why, $do, $we, $count]); +?> +--EXPECT-- +object(Closure)#1 (0) { +} diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 5e46b5d3570..5a873196fb6 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -550,16 +550,31 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) if (closure->func.type == ZEND_USER_FUNCTION && closure->func.op_array.static_variables) { zval *var; - HashTable *static_variables = - ZEND_MAP_PTR_GET(closure->func.op_array.static_variables_ptr); - ZVAL_ARR(&val, zend_array_dup(static_variables)); - zend_hash_update(debug_info, ZSTR_KNOWN(ZEND_STR_STATIC), &val); - ZEND_HASH_FOREACH_VAL(Z_ARRVAL(val), var) { + zend_string *key; + HashTable *static_variables = ZEND_MAP_PTR_GET(closure->func.op_array.static_variables_ptr); + + array_init(&val); + + ZEND_HASH_FOREACH_STR_KEY_VAL(static_variables, key, var) { + zval copy; + if (Z_TYPE_P(var) == IS_CONSTANT_AST) { - zval_ptr_dtor(var); - ZVAL_STRING(var, ""); + ZVAL_STRING(©, ""); + } else { + if (Z_ISREF_P(var) && Z_REFCOUNT_P(var) == 1) { + var = Z_REFVAL_P(var); + } + ZVAL_COPY(©, var); } + + zend_hash_add_new(Z_ARRVAL(val), key, ©); } ZEND_HASH_FOREACH_END(); + + if (zend_hash_num_elements(Z_ARRVAL(val))) { + zend_hash_update(debug_info, ZSTR_KNOWN(ZEND_STR_STATIC), &val); + } else { + zval_ptr_dtor(&val); + } } if (Z_TYPE(closure->this_ptr) != IS_UNDEF) {