[VarDumper] fix very special vars handling

This commit is contained in:
Nicolas Grekas 2015-01-08 11:41:30 +01:00
parent ed2e6b70d1
commit e26dc2c958
5 changed files with 163 additions and 4 deletions

View File

@ -50,7 +50,7 @@ class DumpDataCollectorTest extends \PHPUnit_Framework_TestCase
$this->assertSame($xDump, $dump);
$this->assertStringStartsWith(
'a:1:{i:0;a:5:{s:4:"data";O:39:"Symfony\Component\VarDumper\Cloner\Data":4:{s:45:"Symfony\Component\VarDumper\Cloner\Datadata";a:1:{i:0;a:1:{i:0;i:123;}}s:49:"Symfony\Component\VarDumper\Cloner\DatamaxDepth";i:-1;s:57:"Symfony\Component\VarDumper\Cloner\DatamaxItemsPerDepth";i:-1;s:54:"Symfony\Component\VarDumper\Cloner\DatauseRefHandles";i:-1;}s:4:"name";s:25:"DumpDataCollectorTest.php";s:4:"file";s:',
'a:1:{i:0;a:5:{s:4:"data";O:39:"Symfony\Component\VarDumper\Cloner\Data":4:{s:45:"Symfony\Component\VarDumper\Cloner\Datadata";a:1:{i:0;a:1:{i:0;i:123;}}s:49:"Symfony\Component\VarDumper\Cloner\DatamaxDepth";i:20;s:57:"Symfony\Component\VarDumper\Cloner\DatamaxItemsPerDepth";i:-1;s:54:"Symfony\Component\VarDumper\Cloner\DatauseRefHandles";i:-1;}s:4:"name";s:25:"DumpDataCollectorTest.php";s:4:"file";s:',
str_replace("\0", '', $collector->serialize())
);

View File

@ -82,6 +82,7 @@ abstract class AbstractCloner implements ClonerInterface
protected $maxItems = 2500;
protected $maxString = -1;
protected $useExt;
private $casters = array();
private $prevErrorHandler;
@ -98,6 +99,7 @@ abstract class AbstractCloner implements ClonerInterface
$casters = static::$defaultCasters;
}
$this->addCasters($casters);
$this->useExt = extension_loaded('symfony_debug');
}
/**

View File

@ -17,7 +17,7 @@ namespace Symfony\Component\VarDumper\Cloner;
class Data
{
private $data;
private $maxDepth = -1;
private $maxDepth = 20;
private $maxItemsPerDepth = -1;
private $useRefHandles = -1;

View File

@ -24,7 +24,7 @@ class VarCloner extends AbstractCloner
*/
protected function doClone($var)
{
$useExt = extension_loaded('symfony_debug');
$useExt = $this->useExt;
$i = 0; // Current iteration position in $queue
$len = 1; // Length of $queue
$pos = 0; // Number of cloned items past the first level
@ -120,7 +120,19 @@ class VarCloner extends AbstractCloner
$stub->type = Stub::TYPE_ARRAY;
$stub->class = Stub::ARRAY_ASSOC;
$stub->value = $zval['array_count'] ?: count($v);
$a = $v;
$a[] = null;
$h = count($v);
array_pop($a);
// Happens with copies of $GLOBALS
if ($h !== $stub->value) {
$a = array();
foreach ($v as $gk => &$gv) {
$a[$gk] =& $gv;
}
}
}
break;

View File

@ -104,8 +104,153 @@ array:25 [
EOTXT
,
$out
);
}
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testSpecialVars56()
{
if (PHP_VERSION_ID < 50600) {
$this->markTestSkipped('PHP 5.6 is required');
}
$var = $this->getSpecialVars();
$dumper = new CliDumper();
$dumper->setColors(false);
$cloner = new VarCloner();
$data = $cloner->cloneVar($var);
$out = fopen('php://memory', 'r+b');
$dumper->dump($data, $out);
rewind($out);
$out = stream_get_contents($out);
$this->assertSame(
<<<EOTXT
array:2 [
0 => array:1 [
0 => &1 array:1 [
0 => &1 array:1 [&1]
]
]
1 => array:1 [
"GLOBALS" => &2 array:1 [
"GLOBALS" => &2 array:1 [&2]
]
]
]
EOTXT
,
$out
);
}
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testGlobalsNoExt()
{
$var = $this->getSpecialVars();
unset($var[0]);
$out = '';
$dumper = new CliDumper(function ($line, $depth) use (&$out) {
if ($depth >= 0) {
$out .= str_repeat(' ', $depth).$line."\n";
}
});
$dumper->setColors(false);
$cloner = new VarCloner();
$refl = new \ReflectionProperty($cloner, 'useExt');
$refl->setAccessible(true);
$refl->setValue($cloner, false);
$data = $cloner->cloneVar($var);
$dumper->dump($data);
$this->assertSame(
<<<EOTXT
array:2 [
1 => array:1 [
"GLOBALS" => &1 array:1 [
"GLOBALS" => &1 array:1 [&1]
]
]
2 => &1 array:1 [&1]
]
EOTXT
,
$out
);
}
/**
* @runInSeparateProcess
* @preserveGlobalState disabled
*/
public function testBuggyRefs()
{
if (PHP_VERSION_ID >= 50600) {
$this->markTestSkipped('PHP 5.6 fixed refs counting');
}
$var = $this->getSpecialVars();
$var = $var[0];
$dumper = new CliDumper();
$dumper->setColors(false);
$cloner = new VarCloner();
$data = $cloner->cloneVar($var)->getLimitedClone(3, -1);
$out = '';
$dumper->dump($data, function ($line, $depth) use (&$out) {
if ($depth >= 0) {
$out .= str_repeat(' ', $depth).$line."\n";
}
});
$this->assertSame(
<<<EOTXT
array:1 [
0 => array:1 [
0 => array:1 [
0 => array:1 [
…1
]
]
]
]
EOTXT
,
$out
);
}
private function getSpecialVars()
{
foreach (array_keys($GLOBALS) as $var) {
if ('GLOBALS' !== $var) {
unset($GLOBALS[$var]);
}
}
$var = function &() {
$var = array();
$var[] =& $var;
return $var;
};
return array($var(), $GLOBALS, &$GLOBALS);
}
}