Skip to content

Commit abbab09

Browse files
committed
Fixed issue #2371: Step debugger initializes lazy ghost objects
1 parent 53a1c87 commit abbab09

File tree

7 files changed

+222
-3
lines changed

7 files changed

+222
-3
lines changed

src/lib/var_export_xml.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -607,12 +607,25 @@ void xdebug_var_export_xml_node(zval **struc, xdebug_str *name, xdebug_xml_node
607607
int extra_children = 0;
608608
zend_property_info *zpi_val;
609609

610-
ALLOC_HASHTABLE(merged_hash);
611-
zend_hash_init(merged_hash, 128, NULL, merged_hash_object_item_dtor, 0);
612-
613610
class_name = Z_OBJCE_P(*struc)->name;
614611
ce = zend_fetch_class(class_name, ZEND_FETCH_CLASS_DEFAULT);
615612

613+
#if PHP_VERSION_ID >= 80400
614+
if (ce->type != ZEND_INTERNAL_CLASS && zend_object_is_lazy(Z_OBJ_P(*struc))) {
615+
xdebug_xml_add_attribute(node, "type", "object");
616+
if (zend_object_is_lazy_proxy(Z_OBJ_P(*struc))) {
617+
xdebug_xml_expand_attribute_value(node, "facet", "lazy-proxy");
618+
} else if (!zend_lazy_object_initialized(Z_OBJ_P(*struc))) {
619+
xdebug_xml_expand_attribute_value(node, "facet", "lazy-ghost");
620+
621+
break; /* Jump out of the function */
622+
}
623+
}
624+
#endif
625+
626+
ALLOC_HASHTABLE(merged_hash);
627+
zend_hash_init(merged_hash, 128, NULL, merged_hash_object_item_dtor, 0);
628+
616629
/* Adding static properties */
617630
xdebug_zend_hash_apply_protection_begin(&ce->properties_info);
618631

tests/debugger/bug02371-001.inc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
class User
3+
{
4+
public int $id;
5+
public string $name;
6+
}
7+
8+
$reflection = new ReflectionClass(User::class);
9+
10+
$user = $reflection->newLazyGhost(function (User $user): void {
11+
throw new \RuntimeException('Initialization should not be called');
12+
});
13+
14+
var_dump($reflection->isUninitializedLazyObject($user));

tests/debugger/bug02371-001.phpt

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
--TEST--
2+
Test for bug #2371: Lazy objects are initialised during debugging
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/../utils.inc';
6+
check_reqs('PHP >= 8.4; dbgp');
7+
?>
8+
--FILE--
9+
<?php
10+
require 'dbgp/dbgpclient.php';
11+
$filename = dirname(__FILE__) . '/bug02371-001.inc';
12+
13+
$commands = array(
14+
"breakpoint_set -t exception -x *",
15+
"breakpoint_set -t line -f file://{$filename} -n 14",
16+
'run',
17+
'property_get -n $user',
18+
'detach',
19+
);
20+
21+
dbgpRunFile( $filename, $commands );
22+
?>
23+
--EXPECTF--
24+
<?xml version="1.0" encoding="iso-8859-1"?>
25+
<init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" fileuri="file://bug02371-001.inc" language="PHP" xdebug:language_version="" protocol_version="1.0" appid=""><engine version=""><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[https://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2099 by Derick Rethans]]></copyright></init>
26+
27+
-> breakpoint_set -i 1 -t exception -x *
28+
<?xml version="1.0" encoding="iso-8859-1"?>
29+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="1" id="{{PID}}0001"></response>
30+
31+
-> breakpoint_set -i 2 -t line -f file://bug02371-001.inc -n 14
32+
<?xml version="1.0" encoding="iso-8859-1"?>
33+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="2" id="{{PID}}0002"></response>
34+
35+
-> run -i 3
36+
<?xml version="1.0" encoding="iso-8859-1"?>
37+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="run" transaction_id="3" status="break" reason="ok"><xdebug:message filename="file://bug02371-001.inc" lineno="14"></xdebug:message></response>
38+
39+
-> property_get -i 4 -n $user
40+
<?xml version="1.0" encoding="iso-8859-1"?>
41+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="property_get" transaction_id="4"><property name="$user" fullname="$user" type="object" facet="lazy-ghost"></property></response>
42+
43+
-> detach -i 5
44+
<?xml version="1.0" encoding="iso-8859-1"?>
45+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="detach" transaction_id="5" status="stopping" reason="ok"></response>

tests/debugger/bug02371-002.inc

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
class User
3+
{
4+
public int $id;
5+
public string $name;
6+
}
7+
8+
$reflection = new ReflectionClass(User::class);
9+
10+
$user = $reflection->newLazyGhost(function (User $user): void {
11+
$user->id = 42;
12+
$user->name = "Elephpant";
13+
});
14+
15+
var_dump($user->id);
16+
17+
var_dump($reflection->isUninitializedLazyObject($user));

tests/debugger/bug02371-002.phpt

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--TEST--
2+
Test for bug #2371: Lazy objects are initialised correctly
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/../utils.inc';
6+
check_reqs('PHP >= 8.4; dbgp');
7+
?>
8+
--FILE--
9+
<?php
10+
require 'dbgp/dbgpclient.php';
11+
$filename = dirname(__FILE__) . '/bug02371-002.inc';
12+
13+
$commands = array(
14+
"breakpoint_set -t line -f file://{$filename} -n 15",
15+
"breakpoint_set -t line -f file://{$filename} -n 17",
16+
'run',
17+
'property_get -n $user',
18+
'run',
19+
'property_get -n $user',
20+
'detach',
21+
);
22+
23+
dbgpRunFile( $filename, $commands );
24+
?>
25+
--EXPECTF--
26+
<?xml version="1.0" encoding="iso-8859-1"?>
27+
<init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" fileuri="file://bug02371-002.inc" language="PHP" xdebug:language_version="" protocol_version="1.0" appid=""><engine version=""><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[https://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2099 by Derick Rethans]]></copyright></init>
28+
29+
-> breakpoint_set -i 1 -t line -f file://bug02371-002.inc -n 15
30+
<?xml version="1.0" encoding="iso-8859-1"?>
31+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="1" id="{{PID}}0001"></response>
32+
33+
-> breakpoint_set -i 2 -t line -f file://bug02371-002.inc -n 17
34+
<?xml version="1.0" encoding="iso-8859-1"?>
35+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="2" id="{{PID}}0002"></response>
36+
37+
-> run -i 3
38+
<?xml version="1.0" encoding="iso-8859-1"?>
39+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="run" transaction_id="3" status="break" reason="ok"><xdebug:message filename="file://bug02371-002.inc" lineno="15"></xdebug:message></response>
40+
41+
-> property_get -i 4 -n $user
42+
<?xml version="1.0" encoding="iso-8859-1"?>
43+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="property_get" transaction_id="4"><property name="$user" fullname="$user" type="object" facet="lazy-ghost"></property></response>
44+
45+
-> run -i 5
46+
<?xml version="1.0" encoding="iso-8859-1"?>
47+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="run" transaction_id="5" status="break" reason="ok"><xdebug:message filename="file://bug02371-002.inc" lineno="17"></xdebug:message></response>
48+
49+
-> property_get -i 6 -n $user
50+
<?xml version="1.0" encoding="iso-8859-1"?>
51+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="property_get" transaction_id="6"><property name="$user" fullname="$user" type="object" classname="User" children="1" numchildren="2" page="0" pagesize="32"><property name="id" fullname="$user-&gt;id" facet="public" type="int"><![CDATA[42]]></property><property name="name" fullname="$user-&gt;name" facet="public" type="string" size="9" encoding="base64"><![CDATA[RWxlcGhwYW50]]></property></property></response>
52+
53+
-> detach -i 7
54+
<?xml version="1.0" encoding="iso-8859-1"?>
55+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="detach" transaction_id="7" status="stopping" reason="ok"></response>

tests/debugger/bug02371-003.inc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
class User
3+
{
4+
public int $id;
5+
public string $name;
6+
}
7+
8+
$reflection = new ReflectionClass(User::class);
9+
10+
$user = $reflection->newLazyProxy(function (User $user): User {
11+
$new = new User();
12+
$new->id = 43;
13+
$new->name = "Bluey";
14+
15+
return $new;
16+
});
17+
18+
var_dump($user->id);
19+
20+
var_dump($reflection->isUninitializedLazyObject($user));

tests/debugger/bug02371-003.phpt

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--TEST--
2+
Test for bug #2371: Lazy proxy objects are initialised correctly
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/../utils.inc';
6+
check_reqs('PHP >= 8.4; dbgp');
7+
?>
8+
--FILE--
9+
<?php
10+
require 'dbgp/dbgpclient.php';
11+
$filename = dirname(__FILE__) . '/bug02371-003.inc';
12+
13+
$commands = array(
14+
"breakpoint_set -t line -f file://{$filename} -n 18",
15+
"breakpoint_set -t line -f file://{$filename} -n 20",
16+
'run',
17+
'property_get -n $user',
18+
'run',
19+
'property_get -n $user',
20+
'detach',
21+
);
22+
23+
dbgpRunFile( $filename, $commands );
24+
?>
25+
--EXPECTF--
26+
<?xml version="1.0" encoding="iso-8859-1"?>
27+
<init xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" fileuri="file://bug02371-003.inc" language="PHP" xdebug:language_version="" protocol_version="1.0" appid=""><engine version=""><![CDATA[Xdebug]]></engine><author><![CDATA[Derick Rethans]]></author><url><![CDATA[https://xdebug.org]]></url><copyright><![CDATA[Copyright (c) 2002-2099 by Derick Rethans]]></copyright></init>
28+
29+
-> breakpoint_set -i 1 -t line -f file://bug02371-003.inc -n 18
30+
<?xml version="1.0" encoding="iso-8859-1"?>
31+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="1" id="{{PID}}0001"></response>
32+
33+
-> breakpoint_set -i 2 -t line -f file://bug02371-003.inc -n 20
34+
<?xml version="1.0" encoding="iso-8859-1"?>
35+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="breakpoint_set" transaction_id="2" id="{{PID}}0002"></response>
36+
37+
-> run -i 3
38+
<?xml version="1.0" encoding="iso-8859-1"?>
39+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="run" transaction_id="3" status="break" reason="ok"><xdebug:message filename="file://bug02371-003.inc" lineno="18"></xdebug:message></response>
40+
41+
-> property_get -i 4 -n $user
42+
<?xml version="1.0" encoding="iso-8859-1"?>
43+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="property_get" transaction_id="4"><property name="$user" fullname="$user" type="object" facet="lazy-proxy" type="object" classname="User" children="1" numchildren="2" page="0" pagesize="32"><property name="id" fullname="$user-&gt;id" facet="public" type="int"><![CDATA[43]]></property><property name="name" fullname="$user-&gt;name" facet="public" type="string" size="5" encoding="base64"><![CDATA[Qmx1ZXk=]]></property></property></response>
44+
45+
-> run -i 5
46+
<?xml version="1.0" encoding="iso-8859-1"?>
47+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="run" transaction_id="5" status="break" reason="ok"><xdebug:message filename="file://bug02371-003.inc" lineno="20"></xdebug:message></response>
48+
49+
-> property_get -i 6 -n $user
50+
<?xml version="1.0" encoding="iso-8859-1"?>
51+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="property_get" transaction_id="6"><property name="$user" fullname="$user" type="object" facet="lazy-proxy" type="object" classname="User" children="1" numchildren="2" page="0" pagesize="32"><property name="id" fullname="$user-&gt;id" facet="public" type="int"><![CDATA[43]]></property><property name="name" fullname="$user-&gt;name" facet="public" type="string" size="5" encoding="base64"><![CDATA[Qmx1ZXk=]]></property></property></response>
52+
53+
-> detach -i 7
54+
<?xml version="1.0" encoding="iso-8859-1"?>
55+
<response xmlns="urn:debugger_protocol_v1" xmlns:xdebug="https://xdebug.org/dbgp/xdebug" command="detach" transaction_id="7" status="stopping" reason="ok"></response>

0 commit comments

Comments
 (0)