diff options
Diffstat (limited to 'ext/spl/tests/bug65328.phpt')
-rw-r--r-- | ext/spl/tests/bug65328.phpt | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/ext/spl/tests/bug65328.phpt b/ext/spl/tests/bug65328.phpt new file mode 100644 index 000000000..32e6c24fa --- /dev/null +++ b/ext/spl/tests/bug65328.phpt @@ -0,0 +1,348 @@ +--TEST-- +Bug #65328 (Segfault when getting SplStack object Value) +--FILE-- +<?php +/** + * @author AlexanderC + */ + +class Tree +{ + /** + * @var Node + */ + protected $head; + + /** + * @param Node $head + */ + public function __construct(Node $head = null) + { + $this->head = $head ? : new Node('HEAD'); + } + + /** + * @return Node + */ + public function getHead() + { + return $this->head; + } + + /** + * @param mixed $uid + * @return Node|bool + */ + public function find($uid) + { + $iterator = $this->getIterator(); + + /** @var Node $node */ + foreach($iterator as $node) { + if($node->getUid() === $uid) { + return $node; + } + } + + return false; + } + + /** + * @param mixed $uid + * @return \SplStack + */ + public function & findAll($uid) + { + $result = new \SplStack(); + + /** @var Node $node */ + foreach($this->getIterator() as $node) { + if($node->getUid() == $uid) { + $result->push($node); + } + } + + return $result; + } + + /** + * @return \RecursiveIteratorIterator + */ + public function getIterator() + { + return new \RecursiveIteratorIterator( + $this->head->getChildren(), + \RecursiveIteratorIterator::SELF_FIRST + ); + } +} + +class Node extends \RecursiveArrayIterator implements \Countable +{ + /** + * @var array + */ + protected $children = []; + + /** + * @var Node + */ + protected $parent; + + /** + * @var mixed + */ + protected $data; + + /** + * @var mixed + */ + protected $uid; + + /** + * @var int + */ + protected $index = 0; + + /** + * @var bool + */ + protected $assureUnique; + + /** + * @param mixed $data + * @param mixed $uid + * @param Node $parent + * @param bool $assureUnique + */ + public function __construct($data, $uid = null, Node $parent = null, $assureUnique = false) + { + if(null !== $parent) { + $this->parent = $parent; + } + + $this->data = $data; + $this->uid = $uid ? : uniqid(sha1(serialize($data)), true); + $this->assureUnique = $assureUnique; + } + + /** + * @param mixed $uid + */ + public function setUid($uid) + { + $this->uid = $uid; + } + + /** + * @return mixed + */ + public function getUid() + { + return $this->uid; + } + + /** + * @param Node $child + */ + public function addChild(Node $child) + { + $child->setParent($this); + $this->children[] = $child; + } + + /** + * @param array $children + */ + public function setChildren(array $children) + { + $this->children = $children; + } + + /** + * @return array + */ + public function getChildrenArray() + { + return $this->children; + } + + /** + * @param mixed $data + */ + public function setData($data) + { + $this->data = $data; + } + + /** + * @return mixed + */ + public function getData() + { + return $this->data; + } + + /** + * @param Node $parent + * @throws \RuntimeException + */ + public function setParent(Node $parent) + { + if(true === $this->assureUnique && !self::checkUnique($parent, $this->uid)) { + throw new \RuntimeException("Node uid is not unique in assigned node tree"); + } + + $this->parent = $parent; + } + + /** + * @param Node $node + * @param mixed $uid + * @return bool + */ + protected static function checkUnique(Node $node, $uid) + { + $headNode = $node; + do { + $headNode = $node; + } while($node = $node->getParent()); + + $tree = new Tree($headNode); + + return !$tree->find($uid); + } + + /** + * @return \IJsonRPC\Helpers\Tree\Node + */ + public function getParent() + { + return $this->parent; + } + + /** + * @return Node + */ + public function current() + { + return $this->children[$this->index]; + } + + /** + * @return scalar + */ + public function key() + { + return $this->index; + } + + /** + * @return void + */ + public function next() + { + ++$this->index; + } + + /** + * @return void + */ + public function rewind() + { + $this->index = 0; + } + + /** + * @return bool + */ + public function valid() + { + return array_key_exists($this->index, $this->children); + } + + /** + * @return int + */ + public function count() + { + return count($this->children); + } + + /** + * @return bool + */ + public function hasChildren() + { + return !empty($this->children); + } + + /** + * @return \RecursiveArrayIterator + */ + public function getChildren() + { + return new \RecursiveArrayIterator($this->children); + } +} + +$tree = new Tree(); +$node1 = new Node('value1', 1); +$tree->getHead()->addChild($node1); +$node2 = new Node('value2', 2); +$node1->addChild($node2); + +print_r($tree->findAll(2)->offsetGet(0)); +--EXPECTF-- +Node Object +( + [children:protected] => Array + ( + ) + + [parent:protected] => Node Object + ( + [children:protected] => Array + ( + [0] => Node Object + *RECURSION* + ) + + [parent:protected] => Node Object + ( + [children:protected] => Array + ( + [0] => Node Object + *RECURSION* + ) + + [parent:protected] => + [data:protected] => HEAD + [uid:protected] => %s + [index:protected] => 0 + [assureUnique:protected] => + [storage:ArrayIterator:private] => Array + ( + ) + + ) + + [data:protected] => value1 + [uid:protected] => 1 + [index:protected] => 1 + [assureUnique:protected] => + [storage:ArrayIterator:private] => Array + ( + ) + + ) + + [data:protected] => value2 + [uid:protected] => 2 + [index:protected] => 0 + [assureUnique:protected] => + [storage:ArrayIterator:private] => Array + ( + ) + +) |