Skip to content

Commit 84e2994

Browse files
[VarDumper] fix very special vars handling
1 parent 36af986 commit 84e2994

File tree

4 files changed

+161
-2
lines changed

4 files changed

+161
-2
lines changed

Cloner/AbstractCloner.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ abstract class AbstractCloner implements ClonerInterface
8282

8383
protected $maxItems = 2500;
8484
protected $maxString = -1;
85+
protected $useExt;
8586

8687
private $casters = array();
8788
private $prevErrorHandler;
@@ -98,6 +99,7 @@ public function __construct(array $casters = null)
9899
$casters = static::$defaultCasters;
99100
}
100101
$this->addCasters($casters);
102+
$this->useExt = extension_loaded('symfony_debug');
101103
}
102104

103105
/**

Cloner/Data.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
class Data
1818
{
1919
private $data;
20-
private $maxDepth = -1;
20+
private $maxDepth = 20;
2121
private $maxItemsPerDepth = -1;
2222
private $useRefHandles = -1;
2323

Cloner/VarCloner.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class VarCloner extends AbstractCloner
2424
*/
2525
protected function doClone($var)
2626
{
27-
$useExt = extension_loaded('symfony_debug');
27+
$useExt = $this->useExt;
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
@@ -120,7 +120,19 @@ protected function doClone($var)
120120
$stub->type = Stub::TYPE_ARRAY;
121121
$stub->class = Stub::ARRAY_ASSOC;
122122
$stub->value = $zval['array_count'] ?: count($v);
123+
123124
$a = $v;
125+
$a[] = null;
126+
$h = count($v);
127+
array_pop($a);
128+
129+
// Happens with copies of $GLOBALS
130+
if ($h !== $stub->value) {
131+
$a = array();
132+
foreach ($v as $gk => &$gv) {
133+
$a[$gk] =& $gv;
134+
}
135+
}
124136
}
125137
break;
126138

Tests/CliDumperTest.php

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,153 @@ public function testGet()
104104
105105
EOTXT
106106
,
107+
$out
108+
);
109+
}
110+
111+
/**
112+
* @runInSeparateProcess
113+
* @preserveGlobalState disabled
114+
*/
115+
public function testSpecialVars56()
116+
{
117+
if (PHP_VERSION_ID < 50600) {
118+
$this->markTestSkipped('PHP 5.6 is required');
119+
}
120+
121+
$var = $this->getSpecialVars();
122+
123+
$dumper = new CliDumper();
124+
$dumper->setColors(false);
125+
$cloner = new VarCloner();
126+
127+
$data = $cloner->cloneVar($var);
128+
$out = fopen('php://memory', 'r+b');
129+
$dumper->dump($data, $out);
130+
rewind($out);
131+
$out = stream_get_contents($out);
132+
133+
$this->assertSame(
134+
<<<EOTXT
135+
array:2 [
136+
0 => array:1 [
137+
0 => &1 array:1 [
138+
0 => &1 array:1 [&1]
139+
]
140+
]
141+
1 => array:1 [
142+
"GLOBALS" => &2 array:1 [
143+
"GLOBALS" => &2 array:1 [&2]
144+
]
145+
]
146+
]
107147
148+
EOTXT
149+
,
108150
$out
109151
);
110152
}
153+
154+
/**
155+
* @runInSeparateProcess
156+
* @preserveGlobalState disabled
157+
*/
158+
public function testGlobalsNoExt()
159+
{
160+
$var = $this->getSpecialVars();
161+
unset($var[0]);
162+
$out = '';
163+
164+
$dumper = new CliDumper(function ($line, $depth) use (&$out) {
165+
if ($depth >= 0) {
166+
$out .= str_repeat(' ', $depth).$line."\n";
167+
}
168+
});
169+
$dumper->setColors(false);
170+
$cloner = new VarCloner();
171+
172+
$refl = new \ReflectionProperty($cloner, 'useExt');
173+
$refl->setAccessible(true);
174+
$refl->setValue($cloner, false);
175+
176+
$data = $cloner->cloneVar($var);
177+
$dumper->dump($data);
178+
179+
$this->assertSame(
180+
<<<EOTXT
181+
array:2 [
182+
1 => array:1 [
183+
"GLOBALS" => &1 array:1 [
184+
"GLOBALS" => &1 array:1 [&1]
185+
]
186+
]
187+
2 => &1 array:1 [&1]
188+
]
189+
190+
EOTXT
191+
,
192+
$out
193+
);
194+
}
195+
196+
/**
197+
* @runInSeparateProcess
198+
* @preserveGlobalState disabled
199+
*/
200+
public function testBuggyRefs()
201+
{
202+
if (PHP_VERSION_ID >= 50600) {
203+
$this->markTestSkipped('PHP 5.6 fixed refs counting');
204+
}
205+
206+
$var = $this->getSpecialVars();
207+
$var = $var[0];
208+
209+
$dumper = new CliDumper();
210+
$dumper->setColors(false);
211+
$cloner = new VarCloner();
212+
213+
$data = $cloner->cloneVar($var)->getLimitedClone(3, -1);
214+
$out = '';
215+
$dumper->dump($data, function ($line, $depth) use (&$out) {
216+
if ($depth >= 0) {
217+
$out .= str_repeat(' ', $depth).$line."\n";
218+
}
219+
});
220+
221+
$this->assertSame(
222+
<<<EOTXT
223+
array:1 [
224+
0 => array:1 [
225+
0 => array:1 [
226+
0 => array:1 [
227+
…1
228+
]
229+
]
230+
]
231+
]
232+
233+
EOTXT
234+
,
235+
$out
236+
);
237+
}
238+
239+
private function getSpecialVars()
240+
{
241+
foreach (array_keys($GLOBALS) as $var) {
242+
if ('GLOBALS' !== $var) {
243+
unset($GLOBALS[$var]);
244+
}
245+
}
246+
247+
$var = function &() {
248+
$var = array();
249+
$var[] =& $var;
250+
251+
return $var;
252+
};
253+
254+
return array($var(), $GLOBALS, &$GLOBALS);
255+
}
111256
}

0 commit comments

Comments
 (0)