Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 56549e7

Browse filesBrowse files
[VarDumper] Fix dumping jsons casted as arrays
1 parent d303b9d commit 56549e7
Copy full SHA for 56549e7

File tree

Expand file treeCollapse file tree

5 files changed

+156
-25
lines changed
Filter options
Expand file treeCollapse file tree

5 files changed

+156
-25
lines changed

‎src/Symfony/Component/VarDumper/Caster/Caster.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/Caster/Caster.php
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,16 @@ public static function castObject($obj, \ReflectionClass $reflector)
4545
{
4646
if ($reflector->hasMethod('__debugInfo')) {
4747
$a = $obj->__debugInfo();
48+
} elseif ($obj instanceof \Closure) {
49+
$a = array();
4850
} else {
4951
$a = (array) $obj;
5052
}
5153

5254
if ($a) {
5355
$p = array_keys($a);
5456
foreach ($p as $i => $k) {
55-
if (!isset($k[0]) || ("\0" !== $k[0] && !$reflector->hasProperty($k))) {
57+
if (isset($k[0]) && "\0" !== $k[0] && !$reflector->hasProperty($k)) {
5658
$p[$i] = self::PREFIX_DYNAMIC.$k;
5759
} elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) {
5860
$p[$i] = "\0".$reflector->getParentClass().'@anonymous'.strrchr($k, "\0");

‎src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public static function castClosure(\Closure $c, array $a, Stub $stub, $isNested)
6969
}
7070

7171
$prefix = Caster::PREFIX_DYNAMIC;
72-
unset($a['name'], $a[$prefix.'0'], $a[$prefix.'this'], $a[$prefix.'parameter'], $a[Caster::PREFIX_VIRTUAL.'extra']);
72+
unset($a['name'], $a[$prefix.'this'], $a[$prefix.'parameter'], $a[Caster::PREFIX_VIRTUAL.'extra']);
7373

7474
return $a;
7575
}

‎src/Symfony/Component/VarDumper/Cloner/VarCloner.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/Cloner/VarCloner.php
+47-23Lines changed: 47 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ protected function doClone($var)
2828
$i = 0; // Current iteration position in $queue
2929
$len = 1; // Length of $queue
3030
$pos = 0; // Number of cloned items past the first level
31-
$refs = 0; // Hard references counter
31+
$refsCounter = 0; // Hard references counter
3232
$queue = array(array($var)); // This breadth-first queue is the return value
3333
$arrayRefs = array(); // Map of queue indexes to stub array objects
3434
$hardRefs = array(); // Map of original zval hashes to stub objects
@@ -60,27 +60,32 @@ protected function doClone($var)
6060
for ($i = 0; $i < $len; ++$i) {
6161
$indexed = true; // Whether the currently iterated array is numerically indexed or not
6262
$j = -1; // Position in the currently iterated array
63-
$step = $queue[$i]; // Copy of the currently iterated array used for hard references detection
64-
foreach ($step as $k => $v) {
63+
$fromObjCast = array_keys($queue[$i]);
64+
$fromObjCast = array_keys(array_flip($fromObjCast)) !== $fromObjCast;
65+
$refs = $vals = $fromObjCast ? array_values($queue[$i]) : $queue[$i];
66+
foreach ($queue[$i] as $k => $v) {
6567
// $k is the original key
6668
// $v is the original value or a stub object in case of hard references
67-
if ($indexed && $k !== ++$j) {
69+
if ($k !== ++$j) {
6870
$indexed = false;
6971
}
72+
if ($fromObjCast) {
73+
$k = $j;
74+
}
7075
if ($useExt) {
71-
$zval = symfony_zval_info($k, $step);
76+
$zval = symfony_zval_info($k, $refs);
7277
} else {
73-
$step[$k] = $cookie;
74-
if ($zval['zval_isref'] = $queue[$i][$k] === $cookie) {
78+
$refs[$k] = $cookie;
79+
if ($zval['zval_isref'] = $vals[$k] === $cookie) {
7580
$zval['zval_hash'] = $v instanceof Stub ? spl_object_hash($v) : null;
7681
}
7782
$zval['type'] = gettype($v);
7883
}
7984
if ($zval['zval_isref']) {
80-
$queue[$i][$k] = &$stub; // Break hard references to make $queue completely
85+
$vals[$k] = &$stub; // Break hard references to make $queue completely
8186
unset($stub); // independent from the original structure
8287
if (isset($hardRefs[$zval['zval_hash']])) {
83-
$queue[$i][$k] = $useExt ? ($v = $hardRefs[$zval['zval_hash']]) : ($step[$k] = $v);
88+
$vals[$k] = $useExt ? ($v = $hardRefs[$zval['zval_hash']]) : ($refs[$k] = $v);
8489
if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) {
8590
++$v->value->refCount;
8691
}
@@ -204,18 +209,18 @@ protected function doClone($var)
204209
if (isset($stub)) {
205210
if ($zval['zval_isref']) {
206211
if ($useExt) {
207-
$queue[$i][$k] = $hardRefs[$zval['zval_hash']] = $v = new Stub();
212+
$vals[$k] = $hardRefs[$zval['zval_hash']] = $v = new Stub();
208213
$v->value = $stub;
209214
} else {
210-
$step[$k] = new Stub();
211-
$step[$k]->value = $stub;
212-
$h = spl_object_hash($step[$k]);
213-
$queue[$i][$k] = $hardRefs[$h] = &$step[$k];
215+
$refs[$k] = new Stub();
216+
$refs[$k]->value = $stub;
217+
$h = spl_object_hash($refs[$k]);
218+
$vals[$k] = $hardRefs[$h] = &$refs[$k];
214219
$values[$h] = $v;
215220
}
216-
$queue[$i][$k]->handle = ++$refs;
221+
$vals[$k]->handle = ++$refsCounter;
217222
} else {
218-
$queue[$i][$k] = $stub;
223+
$vals[$k] = $stub;
219224
}
220225

221226
if ($a) {
@@ -243,19 +248,38 @@ protected function doClone($var)
243248
$stub = $a = null;
244249
} elseif ($zval['zval_isref']) {
245250
if ($useExt) {
246-
$queue[$i][$k] = $hardRefs[$zval['zval_hash']] = new Stub();
247-
$queue[$i][$k]->value = $v;
251+
$vals[$k] = $hardRefs[$zval['zval_hash']] = new Stub();
252+
$vals[$k]->value = $v;
248253
} else {
249-
$step[$k] = $queue[$i][$k] = new Stub();
250-
$step[$k]->value = $v;
251-
$h = spl_object_hash($step[$k]);
252-
$hardRefs[$h] = &$step[$k];
254+
$refs[$k] = $vals[$k] = new Stub();
255+
$refs[$k]->value = $v;
256+
$h = spl_object_hash($refs[$k]);
257+
$hardRefs[$h] = &$refs[$k];
253258
$values[$h] = $v;
254259
}
255-
$queue[$i][$k]->handle = ++$refs;
260+
$vals[$k]->handle = ++$refsCounter;
261+
}
262+
}
263+
264+
if ($fromObjCast) {
265+
$refs = $vals;
266+
$vals = array();
267+
$j = -1;
268+
foreach ($queue[$i] as $k => $v) {
269+
foreach (array($k => $v) as $a => $v) {
270+
}
271+
if ($a !== $k) {
272+
$vals = (object) $vals;
273+
$vals->{$k} = $refs[++$j];
274+
$vals = (array) $vals;
275+
} else {
276+
$vals[$k] = $refs[++$j];
277+
}
256278
}
257279
}
258280

281+
$queue[$i] = $vals;
282+
259283
if (isset($arrayRefs[$i])) {
260284
if ($indexed) {
261285
$arrayRefs[$i]->class = Stub::ARRAY_INDEXED;

‎src/Symfony/Component/VarDumper/Tests/CliDumperTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/Tests/CliDumperTest.php
+39Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,45 @@ public function testXmlResource()
133133
);
134134
}
135135

136+
public function testJsonCast()
137+
{
138+
$var = (array) json_decode('{"0":{},"1":null}');
139+
foreach ($var as &$v) {
140+
}
141+
$var[] = &$v;
142+
$var[''] = 2;
143+
144+
$this->assertDumpMatchesFormat(
145+
<<<EOTXT
146+
array:4 [
147+
"0" => {}
148+
"1" => &1 null
149+
0 => &1 null
150+
"" => 2
151+
]
152+
EOTXT
153+
,
154+
$var
155+
);
156+
}
157+
158+
public function testObjectCast()
159+
{
160+
$var = (object) array(1 => 1);
161+
$var->{1} = 2;
162+
163+
$this->assertDumpMatchesFormat(
164+
<<<EOTXT
165+
{
166+
+1: 1
167+
+"1": 2
168+
}
169+
EOTXT
170+
,
171+
$var
172+
);
173+
}
174+
136175
public function testClosedResource()
137176
{
138177
if (defined('HHVM_VERSION') && HHVM_VERSION_ID < 30600) {

‎src/Symfony/Component/VarDumper/Tests/VarClonerTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/VarDumper/Tests/VarClonerTest.php
+66Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,72 @@ public function testClone()
135135
$this->assertStringMatchesFormat($expected, print_r($clone, true));
136136
}
137137

138+
public function testJsonCast()
139+
{
140+
$data = (array) json_decode('{"1":{}}');
141+
142+
$cloner = new VarCloner();
143+
$clone = $cloner->cloneVar($data);
144+
145+
$expected = <<<'EOTXT'
146+
object(Symfony\Component\VarDumper\Cloner\Data)#%i (4) {
147+
["data":"Symfony\Component\VarDumper\Cloner\Data":private]=>
148+
array(2) {
149+
[0]=>
150+
array(1) {
151+
[0]=>
152+
object(Symfony\Component\VarDumper\Cloner\Stub)#%i (7) {
153+
["type"]=>
154+
string(5) "array"
155+
["class"]=>
156+
string(5) "assoc"
157+
["value"]=>
158+
int(1)
159+
["cut"]=>
160+
int(0)
161+
["handle"]=>
162+
int(0)
163+
["refCount"]=>
164+
int(0)
165+
["position"]=>
166+
int(1)
167+
}
168+
}
169+
[1]=>
170+
array(1) {
171+
["1"]=>
172+
object(Symfony\Component\VarDumper\Cloner\Stub)#%i (7) {
173+
["type"]=>
174+
string(6) "object"
175+
["class"]=>
176+
string(8) "stdClass"
177+
["value"]=>
178+
NULL
179+
["cut"]=>
180+
int(0)
181+
["handle"]=>
182+
int(%i)
183+
["refCount"]=>
184+
int(0)
185+
["position"]=>
186+
int(0)
187+
}
188+
}
189+
}
190+
["maxDepth":"Symfony\Component\VarDumper\Cloner\Data":private]=>
191+
int(20)
192+
["maxItemsPerDepth":"Symfony\Component\VarDumper\Cloner\Data":private]=>
193+
int(-1)
194+
["useRefHandles":"Symfony\Component\VarDumper\Cloner\Data":private]=>
195+
int(-1)
196+
}
197+
198+
EOTXT;
199+
ob_start();
200+
var_dump($clone);
201+
$this->assertStringMatchesFormat($expected, ob_get_clean());
202+
}
203+
138204
public function testCaster()
139205
{
140206
$cloner = new VarCloner(array(

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.