From e45e64b7a4bfb86ef218a367aade7310c6cf53e0 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 24 May 2021 07:26:56 +0200 Subject: [PATCH 1/3] Fix #81076 Invalid implicit binds cause incorrect count in static vars of closure debug info --- Zend/tests/bug81076.phpt | 9 +++++++++ Zend/zend_closures.c | 26 ++++++++++++++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 Zend/tests/bug81076.phpt diff --git a/Zend/tests/bug81076.phpt b/Zend/tests/bug81076.phpt new file mode 100644 index 0000000000000..27d5d8d10f1e4 --- /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 ad8e68b9c8f40..7ac986c298b29 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -515,16 +515,30 @@ 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; + zend_string *key; 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_array_dup(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 { + 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); + } + zend_array_release(static_variables); } if (Z_TYPE(closure->this_ptr) != IS_UNDEF) { From 560469b13c72c41ff81536d3d4e969a74aeeb87a Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 24 May 2021 10:34:00 +0200 Subject: [PATCH 2/3] don't dup --- Zend/zend_closures.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 7ac986c298b29..8499b70d9cf9d 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -516,8 +516,7 @@ 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; zend_string *key; - HashTable *static_variables = - zend_array_dup(ZEND_MAP_PTR_GET(closure->func.op_array.static_variables_ptr)); + HashTable *static_variables = ZEND_MAP_PTR_GET(closure->func.op_array.static_variables_ptr); array_init(&val); @@ -527,6 +526,11 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) if (Z_TYPE_P(var) == IS_CONSTANT_AST) { ZVAL_STRING(©, ""); } else { + if (Z_OPT_REFCOUNTED_P(var)) { + if (Z_ISREF_P(var) && Z_REFCOUNT_P(var) == 1) { + var = Z_REFVAL_P(var); + } + } ZVAL_COPY(©, var); } @@ -538,7 +542,6 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) } else { zval_ptr_dtor(&val); } - zend_array_release(static_variables); } if (Z_TYPE(closure->this_ptr) != IS_UNDEF) { From 266e662570039ff949465849d0bd89bd14ee0a7b Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Mon, 24 May 2021 10:59:07 +0200 Subject: [PATCH 3/3] less nest --- Zend/zend_closures.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 8499b70d9cf9d..5ae122b7f94ab 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -526,10 +526,8 @@ static HashTable *zend_closure_get_debug_info(zend_object *object, int *is_temp) if (Z_TYPE_P(var) == IS_CONSTANT_AST) { ZVAL_STRING(©, ""); } else { - if (Z_OPT_REFCOUNTED_P(var)) { - if (Z_ISREF_P(var) && Z_REFCOUNT_P(var) == 1) { - var = Z_REFVAL_P(var); - } + if (Z_ISREF_P(var) && Z_REFCOUNT_P(var) == 1) { + var = Z_REFVAL_P(var); } ZVAL_COPY(©, var); }