Skip to content

Commit 3ffd495

Browse files
committed
[VarDumper] Fix serialization of stubs with null or uninitialized values
1 parent ca8c10d commit 3ffd495

File tree

3 files changed

+89
-4
lines changed

3 files changed

+89
-4
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarDumper\Cloner\Internal;
13+
14+
/**
15+
* Flags a typed property that has no default value.
16+
*
17+
* This dummy object is used to distinguish a property with a default value of null
18+
* from a property that is uninitialized by default.
19+
*
20+
* @internal
21+
*/
22+
enum NoDefault
23+
{
24+
case NoDefault;
25+
}

src/Symfony/Component/VarDumper/Cloner/Stub.php

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\VarDumper\Cloner;
1313

14+
use Symfony\Component\VarDumper\Cloner\Internal\NoDefault;
15+
1416
/**
1517
* Represents the main properties of a PHP variable.
1618
*
@@ -50,15 +52,20 @@ public function __sleep(): array
5052
$properties = [];
5153

5254
if (!isset(self::$defaultProperties[$c = static::class])) {
53-
self::$defaultProperties[$c] = get_class_vars($c);
55+
$reflection = new \ReflectionClass($c);
56+
self::$defaultProperties[$c] = [];
57+
58+
foreach ($reflection->getProperties() as $p) {
59+
if ($p->isStatic()) {
60+
continue;
61+
}
5462

55-
foreach ((new \ReflectionClass($c))->getStaticProperties() as $k => $v) {
56-
unset(self::$defaultProperties[$c][$k]);
63+
self::$defaultProperties[$c][$p->name] = $p->hasDefaultValue() ? $p->getDefaultValue() : ($p->hasType() ? NoDefault::NoDefault : null);
5764
}
5865
}
5966

6067
foreach (self::$defaultProperties[$c] as $k => $v) {
61-
if ($this->$k !== $v) {
68+
if (NoDefault::NoDefault === $v || $this->$k !== $v) {
6269
$properties[] = $k;
6370
}
6471
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\VarDumper\Tests\Cloner;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\VarDumper\Cloner\Stub;
16+
17+
final class StubTest extends TestCase
18+
{
19+
public function testUnserializeNullValue()
20+
{
21+
$stub = new Stub();
22+
$stub->value = null;
23+
24+
$stub = unserialize(serialize($stub));
25+
26+
self::assertNull($stub->value);
27+
}
28+
29+
public function testUnserializeNullInTypedProperty()
30+
{
31+
$stub = new MyStub();
32+
$stub->myProp = null;
33+
34+
$stub = unserialize(serialize($stub));
35+
36+
self::assertNull($stub->myProp);
37+
}
38+
39+
public function testUninitializedStubPropertiesAreLeftUninitialized()
40+
{
41+
$stub = new MyStub();
42+
43+
$stub = unserialize(serialize($stub));
44+
45+
$r = new \ReflectionProperty(MyStub::class, 'myProp');
46+
self::assertFalse($r->isInitialized($stub));
47+
}
48+
}
49+
50+
final class MyStub extends Stub
51+
{
52+
public mixed $myProp;
53+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy