Skip to content

Commit 500b4b4

Browse files
committed
Explicitly print reference wrappers in debug_zval_dump()
Closes GH-6750.
1 parent 4b59071 commit 500b4b4

File tree

6 files changed

+142
-56
lines changed

6 files changed

+142
-56
lines changed

UPGRADING

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ PHP 8.1 UPGRADE NOTES
107107
that ' is escaped to ' while previously it was left alone.
108108
Additionally, malformed UTF-8 will be replaced by a Unicode substitution
109109
character, instead of resulting in an empty string.
110+
. debug_zval_dump() will now print reference wrappers with their refcount,
111+
instead of only prepending a "&" to the value. This more accurately models
112+
reference representation since PHP 7.0.
113+
. debug_zval_dump() will not print "interned" instead of a dummy refcount of
114+
one for interned strings and immutable arrays.
110115

111116
========================================
112117
2. New Features

ext/mysqli/tests/mysqli_result_references.phpt

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,51 +87,69 @@ array(7) refcount(2){
8787
[0]=>
8888
array(2) refcount(1){
8989
["id"]=>
90-
int(1)
90+
reference refcount(1) {
91+
int(1)
92+
}
9193
["label"]=>
9294
string(1) "a" refcount(%d)
9395
}
9496
[1]=>
9597
array(2) refcount(1){
9698
["id"]=>
97-
int(2)
99+
reference refcount(1) {
100+
int(2)
101+
}
98102
["label"]=>
99103
string(1) "b" refcount(%d)
100104
}
101105
[2]=>
102106
array(2) refcount(1){
103107
["id"]=>
104-
int(1)
108+
reference refcount(1) {
109+
int(1)
110+
}
105111
["label"]=>
106112
string(1) "a" refcount(%d)
107113
}
108114
[3]=>
109115
array(2) refcount(1){
110116
["id"]=>
111-
int(2)
117+
reference refcount(1) {
118+
int(2)
119+
}
112120
["label"]=>
113121
string(1) "b" refcount(%d)
114122
}
115123
[4]=>
116124
array(3) refcount(1){
117125
["id"]=>
118-
&int(3)
126+
reference refcount(2) {
127+
int(3)
128+
}
119129
["label"]=>
120130
string(1) "a" refcount(%d)
121131
["id2"]=>
122-
&int(3)
132+
reference refcount(2) {
133+
int(3)
134+
}
123135
}
124136
[5]=>
125137
array(3) refcount(1){
126138
["id"]=>
127-
&int(4)
139+
reference refcount(2) {
140+
int(4)
141+
}
128142
["label"]=>
129143
string(1) "b" refcount(%d)
130144
["id2"]=>
131-
&int(4)
145+
reference refcount(2) {
146+
int(4)
147+
}
132148
}
133149
[6]=>
134-
&object(mysqli_result)#%d (0) refcount(%d){
150+
reference refcount(2) {
151+
object(mysqli_result)#2 (0) refcount(1){
152+
}
135153
}
136154
}
137155
array(1) refcount(2){

ext/mysqli/tests/mysqli_result_references_mysqlnd.phpt

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ array(1) refcount(%d){
5555
[0]=>
5656
array(4) refcount(%d){
5757
["row_ref"]=>
58-
&NULL
58+
reference refcount(2) {
59+
NULL
60+
}
5961
["row_copy"]=>
6062
array(2) refcount(1){
6163
["id"]=>
@@ -64,7 +66,9 @@ array(1) refcount(%d){
6466
string(1) "a" interned
6567
}
6668
["id_ref"]=>
67-
string(1) "1" interned
69+
reference refcount(1) {
70+
string(1) "1" interned
71+
}
6872
["id_copy"]=>
6973
string(1) "1" interned
7074
}
@@ -73,7 +77,9 @@ array(2) refcount(%d){
7377
[0]=>
7478
array(4) refcount(%d){
7579
["row_ref"]=>
76-
&NULL
80+
reference refcount(2) {
81+
NULL
82+
}
7783
["row_copy"]=>
7884
array(2) refcount(%d){
7985
["id"]=>
@@ -82,18 +88,24 @@ array(2) refcount(%d){
8288
string(1) "a" interned
8389
}
8490
["id_ref"]=>
85-
string(1) "1" interned
91+
reference refcount(1) {
92+
string(1) "1" interned
93+
}
8694
["id_copy"]=>
8795
string(1) "1" interned
8896
}
8997
[1]=>
9098
array(5) refcount(%d){
9199
["row_ref"]=>
92-
&array(2) refcount(%d){
93-
["id"]=>
94-
&string(1) "2" interned
95-
["label"]=>
96-
string(1) "b" interned
100+
reference refcount(2) {
101+
array(2) refcount(1){
102+
["id"]=>
103+
reference refcount(2) {
104+
string(1) "2" interned
105+
}
106+
["label"]=>
107+
string(1) "b" interned
108+
}
97109
}
98110
["row_copy"]=>
99111
array(2) refcount(%d){
@@ -103,7 +115,9 @@ array(2) refcount(%d){
103115
string(1) "b" interned
104116
}
105117
["id_ref"]=>
106-
&string(1) "2" interned
118+
reference refcount(2) {
119+
string(1) "2" interned
120+
}
107121
["id_copy"]=>
108122
string(1) "2" interned
109123
["id_copy_mod"]=>

ext/standard/tests/general_functions/debug_zval_dump_o.phpt

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -345,26 +345,30 @@ object(object_class)#%d (7) refcount(%d){
345345
["object_class1"]=>
346346
*RECURSION*
347347
["obj"]=>
348-
&object(object_class)#%d (7) refcount(%d){
349-
["value1"]=>
350-
int(5)
351-
["value2":"object_class":private]=>
352-
int(10)
353-
["value3":protected]=>
354-
int(20)
355-
["value4"]=>
356-
int(30)
357-
["array_var"]=>
358-
array(2) refcount(%d){
359-
["key1"]=>
360-
int(1)
361-
["key2 "]=>
362-
int(3)
348+
reference refcount(2) {
349+
object(object_class)#8 (7) refcount(2){
350+
["value1"]=>
351+
int(5)
352+
["value2":"object_class":private]=>
353+
int(10)
354+
["value3":protected]=>
355+
int(20)
356+
["value4"]=>
357+
int(30)
358+
["array_var"]=>
359+
array(2) refcount(7){
360+
["key1"]=>
361+
int(1)
362+
["key2 "]=>
363+
int(3)
364+
}
365+
["object_class1"]=>
366+
*RECURSION*
367+
["obj"]=>
368+
reference refcount(2) {
369+
*RECURSION*
370+
}
363371
}
364-
["object_class1"]=>
365-
*RECURSION*
366-
["obj"]=>
367-
*RECURSION*
368372
}
369373
}
370374
Done
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--TEST--
2+
References in debug_zval_dump()
3+
--FILE--
4+
<?php
5+
6+
$r = 1;
7+
$a = [&$r];
8+
debug_zval_dump($a);
9+
$a[] =& $r;
10+
debug_zval_dump($a);
11+
unset($a[1]);
12+
debug_zval_dump($a);
13+
unset($r);
14+
// rc=1 singleton ref remains
15+
debug_zval_dump($a);
16+
17+
?>
18+
--EXPECT--
19+
array(1) refcount(2){
20+
[0]=>
21+
reference refcount(2) {
22+
int(1)
23+
}
24+
}
25+
array(2) refcount(2){
26+
[0]=>
27+
reference refcount(3) {
28+
int(1)
29+
}
30+
[1]=>
31+
reference refcount(3) {
32+
int(1)
33+
}
34+
}
35+
array(1) refcount(2){
36+
[0]=>
37+
reference refcount(2) {
38+
int(1)
39+
}
40+
}
41+
array(1) refcount(2){
42+
[0]=>
43+
reference refcount(1) {
44+
int(1)
45+
}
46+
}

ext/standard/var.c

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,6 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */
269269
{
270270
HashTable *myht = NULL;
271271
zend_string *class_name;
272-
int is_ref = 0;
273272
zend_ulong index;
274273
zend_string *key;
275274
zval *val;
@@ -279,25 +278,24 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */
279278
php_printf("%*c", level - 1, ' ');
280279
}
281280

282-
again:
283281
switch (Z_TYPE_P(struc)) {
284282
case IS_FALSE:
285-
php_printf("%sbool(false)\n", COMMON);
283+
PUTS("bool(false)\n");
286284
break;
287285
case IS_TRUE:
288-
php_printf("%sbool(true)\n", COMMON);
286+
PUTS("bool(true)\n");
289287
break;
290288
case IS_NULL:
291-
php_printf("%sNULL\n", COMMON);
289+
PUTS("NULL\n");
292290
break;
293291
case IS_LONG:
294-
php_printf("%sint(" ZEND_LONG_FMT ")\n", COMMON, Z_LVAL_P(struc));
292+
php_printf("int(" ZEND_LONG_FMT ")\n", Z_LVAL_P(struc));
295293
break;
296294
case IS_DOUBLE:
297-
php_printf_unchecked("%sfloat(%.*H)\n", COMMON, (int) PG(serialize_precision), Z_DVAL_P(struc));
295+
php_printf_unchecked("float(%.*H)\n", (int) PG(serialize_precision), Z_DVAL_P(struc));
298296
break;
299297
case IS_STRING:
300-
php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc));
298+
php_printf("string(%zd) \"", Z_STRLEN_P(struc));
301299
PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc));
302300
if (Z_REFCOUNTED_P(struc)) {
303301
php_printf("\" refcount(%u)\n", Z_REFCOUNT_P(struc));
@@ -318,9 +316,9 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */
318316
count = zend_hash_num_elements(myht);
319317
if (Z_REFCOUNTED_P(struc)) {
320318
/* -1 because of ADDREF above. */
321-
php_printf("%sarray(%d) refcount(%u){\n", COMMON, count, Z_REFCOUNT_P(struc) - 1);
319+
php_printf("array(%d) refcount(%u){\n", count, Z_REFCOUNT_P(struc) - 1);
322320
} else {
323-
php_printf("%sarray(%d) interned {\n", COMMON, count);
321+
php_printf("array(%d) interned {\n", count);
324322
}
325323
ZEND_HASH_FOREACH_KEY_VAL(myht, index, key, val) {
326324
zval_array_element_dump(val, index, key, level);
@@ -345,7 +343,7 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */
345343
GC_PROTECT_RECURSION(myht);
346344
}
347345
class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
348-
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));
346+
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));
349347
zend_string_release_ex(class_name, 0);
350348
if (myht) {
351349
ZEND_HASH_FOREACH_KEY_VAL(myht, index, key, val) {
@@ -372,18 +370,19 @@ PHPAPI void php_debug_zval_dump(zval *struc, int level) /* {{{ */
372370
break;
373371
case IS_RESOURCE: {
374372
const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc));
375-
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));
373+
php_printf("resource(%d) of type (%s) refcount(%u)\n", Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc));
376374
break;
377375
}
378376
case IS_REFERENCE:
379-
//??? hide references with refcount==1 (for compatibility)
380-
if (Z_REFCOUNT_P(struc) > 1) {
381-
is_ref = 1;
377+
php_printf("reference refcount(%u) {\n", Z_REFCOUNT_P(struc));
378+
php_debug_zval_dump(Z_REFVAL_P(struc), level + 2);
379+
if (level > 1) {
380+
php_printf("%*c", level - 1, ' ');
382381
}
383-
struc = Z_REFVAL_P(struc);
384-
goto again;
382+
PUTS("}\n");
383+
break;
385384
default:
386-
php_printf("%sUNKNOWN:0\n", COMMON);
385+
PUTS("UNKNOWN:0\n");
387386
break;
388387
}
389388
}

0 commit comments

Comments
 (0)