mirror of
https://github.com/php/php-src.git
synced 2026-04-02 13:43:02 +02:00
Explicitly print reference wrappers in debug_zval_dump()
Closes GH-6750.
This commit is contained in:
@@ -107,6 +107,11 @@ PHP 8.1 UPGRADE NOTES
|
||||
that ' is escaped to ' while previously it was left alone.
|
||||
Additionally, malformed UTF-8 will be replaced by a Unicode substitution
|
||||
character, instead of resulting in an empty string.
|
||||
. debug_zval_dump() will now print reference wrappers with their refcount,
|
||||
instead of only prepending a "&" to the value. This more accurately models
|
||||
reference representation since PHP 7.0.
|
||||
. debug_zval_dump() will not print "interned" instead of a dummy refcount of
|
||||
one for interned strings and immutable arrays.
|
||||
|
||||
========================================
|
||||
2. New Features
|
||||
|
||||
@@ -87,51 +87,69 @@ array(7) refcount(2){
|
||||
[0]=>
|
||||
array(2) refcount(1){
|
||||
["id"]=>
|
||||
int(1)
|
||||
reference refcount(1) {
|
||||
int(1)
|
||||
}
|
||||
["label"]=>
|
||||
string(1) "a" refcount(%d)
|
||||
}
|
||||
[1]=>
|
||||
array(2) refcount(1){
|
||||
["id"]=>
|
||||
int(2)
|
||||
reference refcount(1) {
|
||||
int(2)
|
||||
}
|
||||
["label"]=>
|
||||
string(1) "b" refcount(%d)
|
||||
}
|
||||
[2]=>
|
||||
array(2) refcount(1){
|
||||
["id"]=>
|
||||
int(1)
|
||||
reference refcount(1) {
|
||||
int(1)
|
||||
}
|
||||
["label"]=>
|
||||
string(1) "a" refcount(%d)
|
||||
}
|
||||
[3]=>
|
||||
array(2) refcount(1){
|
||||
["id"]=>
|
||||
int(2)
|
||||
reference refcount(1) {
|
||||
int(2)
|
||||
}
|
||||
["label"]=>
|
||||
string(1) "b" refcount(%d)
|
||||
}
|
||||
[4]=>
|
||||
array(3) refcount(1){
|
||||
["id"]=>
|
||||
&int(3)
|
||||
reference refcount(2) {
|
||||
int(3)
|
||||
}
|
||||
["label"]=>
|
||||
string(1) "a" refcount(%d)
|
||||
["id2"]=>
|
||||
&int(3)
|
||||
reference refcount(2) {
|
||||
int(3)
|
||||
}
|
||||
}
|
||||
[5]=>
|
||||
array(3) refcount(1){
|
||||
["id"]=>
|
||||
&int(4)
|
||||
reference refcount(2) {
|
||||
int(4)
|
||||
}
|
||||
["label"]=>
|
||||
string(1) "b" refcount(%d)
|
||||
["id2"]=>
|
||||
&int(4)
|
||||
reference refcount(2) {
|
||||
int(4)
|
||||
}
|
||||
}
|
||||
[6]=>
|
||||
&object(mysqli_result)#%d (0) refcount(%d){
|
||||
reference refcount(2) {
|
||||
object(mysqli_result)#2 (0) refcount(1){
|
||||
}
|
||||
}
|
||||
}
|
||||
array(1) refcount(2){
|
||||
|
||||
@@ -55,7 +55,9 @@ array(1) refcount(%d){
|
||||
[0]=>
|
||||
array(4) refcount(%d){
|
||||
["row_ref"]=>
|
||||
&NULL
|
||||
reference refcount(2) {
|
||||
NULL
|
||||
}
|
||||
["row_copy"]=>
|
||||
array(2) refcount(1){
|
||||
["id"]=>
|
||||
@@ -64,7 +66,9 @@ array(1) refcount(%d){
|
||||
string(1) "a" interned
|
||||
}
|
||||
["id_ref"]=>
|
||||
string(1) "1" interned
|
||||
reference refcount(1) {
|
||||
string(1) "1" interned
|
||||
}
|
||||
["id_copy"]=>
|
||||
string(1) "1" interned
|
||||
}
|
||||
@@ -73,7 +77,9 @@ array(2) refcount(%d){
|
||||
[0]=>
|
||||
array(4) refcount(%d){
|
||||
["row_ref"]=>
|
||||
&NULL
|
||||
reference refcount(2) {
|
||||
NULL
|
||||
}
|
||||
["row_copy"]=>
|
||||
array(2) refcount(%d){
|
||||
["id"]=>
|
||||
@@ -82,18 +88,24 @@ array(2) refcount(%d){
|
||||
string(1) "a" interned
|
||||
}
|
||||
["id_ref"]=>
|
||||
string(1) "1" interned
|
||||
reference refcount(1) {
|
||||
string(1) "1" interned
|
||||
}
|
||||
["id_copy"]=>
|
||||
string(1) "1" interned
|
||||
}
|
||||
[1]=>
|
||||
array(5) refcount(%d){
|
||||
["row_ref"]=>
|
||||
&array(2) refcount(%d){
|
||||
["id"]=>
|
||||
&string(1) "2" interned
|
||||
["label"]=>
|
||||
string(1) "b" interned
|
||||
reference refcount(2) {
|
||||
array(2) refcount(1){
|
||||
["id"]=>
|
||||
reference refcount(2) {
|
||||
string(1) "2" interned
|
||||
}
|
||||
["label"]=>
|
||||
string(1) "b" interned
|
||||
}
|
||||
}
|
||||
["row_copy"]=>
|
||||
array(2) refcount(%d){
|
||||
@@ -103,7 +115,9 @@ array(2) refcount(%d){
|
||||
string(1) "b" interned
|
||||
}
|
||||
["id_ref"]=>
|
||||
&string(1) "2" interned
|
||||
reference refcount(2) {
|
||||
string(1) "2" interned
|
||||
}
|
||||
["id_copy"]=>
|
||||
string(1) "2" interned
|
||||
["id_copy_mod"]=>
|
||||
|
||||
@@ -345,26 +345,30 @@ object(object_class)#%d (7) refcount(%d){
|
||||
["object_class1"]=>
|
||||
*RECURSION*
|
||||
["obj"]=>
|
||||
&object(object_class)#%d (7) refcount(%d){
|
||||
["value1"]=>
|
||||
int(5)
|
||||
["value2":"object_class":private]=>
|
||||
int(10)
|
||||
["value3":protected]=>
|
||||
int(20)
|
||||
["value4"]=>
|
||||
int(30)
|
||||
["array_var"]=>
|
||||
array(2) refcount(%d){
|
||||
["key1"]=>
|
||||
int(1)
|
||||
["key2 "]=>
|
||||
int(3)
|
||||
reference refcount(2) {
|
||||
object(object_class)#8 (7) refcount(2){
|
||||
["value1"]=>
|
||||
int(5)
|
||||
["value2":"object_class":private]=>
|
||||
int(10)
|
||||
["value3":protected]=>
|
||||
int(20)
|
||||
["value4"]=>
|
||||
int(30)
|
||||
["array_var"]=>
|
||||
array(2) refcount(7){
|
||||
["key1"]=>
|
||||
int(1)
|
||||
["key2 "]=>
|
||||
int(3)
|
||||
}
|
||||
["object_class1"]=>
|
||||
*RECURSION*
|
||||
["obj"]=>
|
||||
reference refcount(2) {
|
||||
*RECURSION*
|
||||
}
|
||||
}
|
||||
["object_class1"]=>
|
||||
*RECURSION*
|
||||
["obj"]=>
|
||||
*RECURSION*
|
||||
}
|
||||
}
|
||||
Done
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
--TEST--
|
||||
References in debug_zval_dump()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$r = 1;
|
||||
$a = [&$r];
|
||||
debug_zval_dump($a);
|
||||
$a[] =& $r;
|
||||
debug_zval_dump($a);
|
||||
unset($a[1]);
|
||||
debug_zval_dump($a);
|
||||
unset($r);
|
||||
// rc=1 singleton ref remains
|
||||
debug_zval_dump($a);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
array(1) refcount(2){
|
||||
[0]=>
|
||||
reference refcount(2) {
|
||||
int(1)
|
||||
}
|
||||
}
|
||||
array(2) refcount(2){
|
||||
[0]=>
|
||||
reference refcount(3) {
|
||||
int(1)
|
||||
}
|
||||
[1]=>
|
||||
reference refcount(3) {
|
||||
int(1)
|
||||
}
|
||||
}
|
||||
array(1) refcount(2){
|
||||
[0]=>
|
||||
reference refcount(2) {
|
||||
int(1)
|
||||
}
|
||||
}
|
||||
array(1) refcount(2){
|
||||
[0]=>
|
||||
reference refcount(1) {
|
||||
int(1)
|
||||
}
|
||||
}
|
||||
@@ -269,7 +269,6 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */
|
||||
{
|
||||
HashTable *myht = NULL;
|
||||
zend_string *class_name;
|
||||
int is_ref = 0;
|
||||
zend_ulong index;
|
||||
zend_string *key;
|
||||
zval *val;
|
||||
@@ -279,25 +278,24 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */
|
||||
php_printf("%*c", level - 1, ' ');
|
||||
}
|
||||
|
||||
again:
|
||||
switch (Z_TYPE_P(struc)) {
|
||||
case IS_FALSE:
|
||||
php_printf("%sbool(false)\n", COMMON);
|
||||
PUTS("bool(false)\n");
|
||||
break;
|
||||
case IS_TRUE:
|
||||
php_printf("%sbool(true)\n", COMMON);
|
||||
PUTS("bool(true)\n");
|
||||
break;
|
||||
case IS_NULL:
|
||||
php_printf("%sNULL\n", COMMON);
|
||||
PUTS("NULL\n");
|
||||
break;
|
||||
case IS_LONG:
|
||||
php_printf("%sint(" ZEND_LONG_FMT ")\n", COMMON, Z_LVAL_P(struc));
|
||||
php_printf("int(" ZEND_LONG_FMT ")\n", Z_LVAL_P(struc));
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
php_printf_unchecked("%sfloat(%.*H)\n", COMMON, (int) PG(serialize_precision), Z_DVAL_P(struc));
|
||||
php_printf_unchecked("float(%.*H)\n", (int) PG(serialize_precision), Z_DVAL_P(struc));
|
||||
break;
|
||||
case IS_STRING:
|
||||
php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc));
|
||||
php_printf("string(%zd) \"", Z_STRLEN_P(struc));
|
||||
PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc));
|
||||
if (Z_REFCOUNTED_P(struc)) {
|
||||
php_printf("\" refcount(%u)\n", Z_REFCOUNT_P(struc));
|
||||
@@ -318,9 +316,9 @@ again:
|
||||
count = zend_hash_num_elements(myht);
|
||||
if (Z_REFCOUNTED_P(struc)) {
|
||||
/* -1 because of ADDREF above. */
|
||||
php_printf("%sarray(%d) refcount(%u){\n", COMMON, count, Z_REFCOUNT_P(struc) - 1);
|
||||
php_printf("array(%d) refcount(%u){\n", count, Z_REFCOUNT_P(struc) - 1);
|
||||
} else {
|
||||
php_printf("%sarray(%d) interned {\n", COMMON, count);
|
||||
php_printf("array(%d) interned {\n", count);
|
||||
}
|
||||
ZEND_HASH_FOREACH_KEY_VAL(myht, index, key, val) {
|
||||
zval_array_element_dump(val, index, key, level);
|
||||
@@ -345,7 +343,7 @@ again:
|
||||
GC_PROTECT_RECURSION(myht);
|
||||
}
|
||||
class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
|
||||
php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0, Z_REFCOUNT_P(struc));
|
||||
php_printf("object(%s)#%d (%d) refcount(%u){\n", ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_array_count(myht) : 0, Z_REFCOUNT_P(struc));
|
||||
zend_string_release_ex(class_name, 0);
|
||||
if (myht) {
|
||||
ZEND_HASH_FOREACH_KEY_VAL(myht, index, key, val) {
|
||||
@@ -372,18 +370,19 @@ again:
|
||||
break;
|
||||
case IS_RESOURCE: {
|
||||
const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc));
|
||||
php_printf("%sresource(%d) of type (%s) refcount(%u)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc));
|
||||
php_printf("resource(%d) of type (%s) refcount(%u)\n", Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc));
|
||||
break;
|
||||
}
|
||||
case IS_REFERENCE:
|
||||
//??? hide references with refcount==1 (for compatibility)
|
||||
if (Z_REFCOUNT_P(struc) > 1) {
|
||||
is_ref = 1;
|
||||
php_printf("reference refcount(%u) {\n", Z_REFCOUNT_P(struc));
|
||||
php_debug_zval_dump(Z_REFVAL_P(struc), level + 2);
|
||||
if (level > 1) {
|
||||
php_printf("%*c", level - 1, ' ');
|
||||
}
|
||||
struc = Z_REFVAL_P(struc);
|
||||
goto again;
|
||||
PUTS("}\n");
|
||||
break;
|
||||
default:
|
||||
php_printf("%sUNKNOWN:0\n", COMMON);
|
||||
PUTS("UNKNOWN:0\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user