Skip to content

Commit 4cbb312

Browse files
Cover allowed-child + unlisted-parent-scope round-trip
allowed_classes gates instantiation. A child that inherits private state from its parent should round-trip on ['Child'] alone — the parent is never instantiated, only used as a scope for the inherited private slot write. The is-a-parent-of check on "properties" entries is the real security boundary.
1 parent 275f490 commit 4cbb312

1 file changed

Lines changed: 20 additions & 0 deletions

File tree

tests/deepclone_allowed_classes.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,23 @@ var_dump($c->x === 1);
9494
$c = deepclone_from_array(['value' => 42], []);
9595
var_dump($c === 42);
9696

97+
// ── from_array: allowed child carries inherited parent-declared private
98+
// state even when the parent isn't listed in $allowedClasses. The scope
99+
// check on "properties" entries (is-a-parent-of obj->ce) is the security
100+
// boundary; allowed_classes is for instantiation. ──
101+
class AllowedParent { private string $secret = ''; public function getSecret(): string { return $this->secret; } }
102+
class AllowedChild extends AllowedParent { public string $pub = ''; }
103+
104+
$c = new AllowedChild();
105+
(function () { $this->secret = 'inherited'; })->bindTo($c, AllowedParent::class)();
106+
$c->pub = 'visible';
107+
108+
$d = deepclone_to_array($c, ['AllowedChild']);
109+
$r = deepclone_from_array($d, ['AllowedChild']);
110+
var_dump($r instanceof AllowedChild);
111+
var_dump($r->getSecret() === 'inherited');
112+
var_dump($r->pub === 'visible');
113+
97114
echo "Done\n";
98115
?>
99116
--EXPECT--
@@ -113,4 +130,7 @@ bool(true)
113130
bool(true)
114131
bool(true)
115132
bool(true)
133+
bool(true)
134+
bool(true)
135+
bool(true)
116136
Done

0 commit comments

Comments
 (0)