Annotation of embedaddon/php/ext/spl/tests/bug65328.phpt, revision 1.1.1.1

1.1       misho       1: --TEST--
                      2: Bug #65328 (Segfault when getting SplStack object Value)
                      3: --FILE--
                      4: <?php
                      5: /**
                      6:  * @author AlexanderC
                      7:  */
                      8: 
                      9: class Tree
                     10: {
                     11:     /**
                     12:      * @var Node
                     13:      */
                     14:     protected $head;
                     15: 
                     16:     /**
                     17:      * @param Node $head
                     18:      */
                     19:     public function __construct(Node $head = null)
                     20:     {
                     21:         $this->head = $head ? : new Node('HEAD');
                     22:     }
                     23: 
                     24:     /**
                     25:      * @return Node
                     26:      */
                     27:     public function getHead()
                     28:     {
                     29:         return $this->head;
                     30:     }
                     31: 
                     32:     /**
                     33:      * @param mixed $uid
                     34:      * @return Node|bool
                     35:      */
                     36:     public function find($uid)
                     37:     {
                     38:         $iterator = $this->getIterator();
                     39: 
                     40:         /** @var Node $node */
                     41:         foreach($iterator as $node) {
                     42:             if($node->getUid() === $uid) {
                     43:                 return $node;
                     44:             }
                     45:         }
                     46: 
                     47:         return false;
                     48:     }
                     49: 
                     50:     /**
                     51:      * @param mixed $uid
                     52:      * @return \SplStack
                     53:      */
                     54:     public function & findAll($uid)
                     55:     {
                     56:         $result = new \SplStack();
                     57: 
                     58:         /** @var Node $node */
                     59:         foreach($this->getIterator() as $node) {
                     60:             if($node->getUid() == $uid) {
                     61:                 $result->push($node);
                     62:             }
                     63:         }
                     64: 
                     65:         return $result;
                     66:     }
                     67: 
                     68:     /**
                     69:      * @return \RecursiveIteratorIterator
                     70:      */
                     71:     public function getIterator()
                     72:     {
                     73:         return new \RecursiveIteratorIterator(
                     74:             $this->head->getChildren(),
                     75:             \RecursiveIteratorIterator::SELF_FIRST
                     76:         );
                     77:     }
                     78: }
                     79: 
                     80: class Node extends \RecursiveArrayIterator implements \Countable
                     81: {
                     82:     /**
                     83:      * @var array
                     84:      */
                     85:     protected $children = [];
                     86: 
                     87:     /**
                     88:      * @var Node
                     89:      */
                     90:     protected $parent;
                     91: 
                     92:     /**
                     93:      * @var mixed
                     94:      */
                     95:     protected $data;
                     96: 
                     97:     /**
                     98:      * @var mixed
                     99:      */
                    100:     protected $uid;
                    101: 
                    102:     /**
                    103:      * @var int
                    104:      */
                    105:     protected $index = 0;
                    106: 
                    107:     /**
                    108:      * @var bool
                    109:      */
                    110:     protected $assureUnique;
                    111: 
                    112:     /**
                    113:      * @param mixed $data
                    114:      * @param mixed $uid
                    115:      * @param Node $parent
                    116:      * @param bool $assureUnique
                    117:      */
                    118:     public function __construct($data, $uid = null, Node $parent = null, $assureUnique = false)
                    119:     {
                    120:         if(null !== $parent) {
                    121:             $this->parent = $parent;
                    122:         }
                    123: 
                    124:         $this->data = $data;
                    125:         $this->uid = $uid ? : uniqid(sha1(serialize($data)), true);
                    126:         $this->assureUnique = $assureUnique;
                    127:     }
                    128: 
                    129:     /**
                    130:      * @param mixed $uid
                    131:      */
                    132:     public function setUid($uid)
                    133:     {
                    134:         $this->uid = $uid;
                    135:     }
                    136: 
                    137:     /**
                    138:      * @return mixed
                    139:      */
                    140:     public function getUid()
                    141:     {
                    142:         return $this->uid;
                    143:     }
                    144: 
                    145:     /**
                    146:      * @param Node $child
                    147:      */
                    148:     public function addChild(Node $child)
                    149:     {
                    150:         $child->setParent($this);
                    151:         $this->children[] = $child;
                    152:     }
                    153: 
                    154:     /**
                    155:      * @param array $children
                    156:      */
                    157:     public function setChildren(array $children)
                    158:     {
                    159:         $this->children = $children;
                    160:     }
                    161: 
                    162:     /**
                    163:      * @return array
                    164:      */
                    165:     public function getChildrenArray()
                    166:     {
                    167:         return $this->children;
                    168:     }
                    169: 
                    170:     /**
                    171:      * @param mixed $data
                    172:      */
                    173:     public function setData($data)
                    174:     {
                    175:         $this->data = $data;
                    176:     }
                    177: 
                    178:     /**
                    179:      * @return mixed
                    180:      */
                    181:     public function getData()
                    182:     {
                    183:         return $this->data;
                    184:     }
                    185: 
                    186:     /**
                    187:      * @param Node $parent
                    188:      * @throws \RuntimeException
                    189:      */
                    190:     public function setParent(Node $parent)
                    191:     {
                    192:         if(true === $this->assureUnique && !self::checkUnique($parent, $this->uid)) {
                    193:             throw new \RuntimeException("Node uid is not unique in assigned node tree");
                    194:         }
                    195: 
                    196:         $this->parent = $parent;
                    197:     }
                    198: 
                    199:     /**
                    200:      * @param Node $node
                    201:      * @param mixed $uid
                    202:      * @return bool
                    203:      */
                    204:     protected static function checkUnique(Node $node, $uid)
                    205:     {
                    206:         $headNode = $node;
                    207:         do {
                    208:             $headNode = $node;
                    209:         } while($node = $node->getParent());
                    210: 
                    211:         $tree = new Tree($headNode);
                    212: 
                    213:         return !$tree->find($uid);
                    214:     }
                    215: 
                    216:     /**
                    217:      * @return \IJsonRPC\Helpers\Tree\Node
                    218:      */
                    219:     public function getParent()
                    220:     {
                    221:         return $this->parent;
                    222:     }
                    223: 
                    224:     /**
                    225:      * @return Node
                    226:      */
                    227:     public function current()
                    228:     {
                    229:         return $this->children[$this->index];
                    230:     }
                    231: 
                    232:     /**
                    233:      * @return scalar
                    234:      */
                    235:     public function key()
                    236:     {
                    237:         return $this->index;
                    238:     }
                    239: 
                    240:     /**
                    241:      * @return void
                    242:      */
                    243:     public function next()
                    244:     {
                    245:         ++$this->index;
                    246:     }
                    247: 
                    248:     /**
                    249:      * @return void
                    250:      */
                    251:     public function rewind()
                    252:     {
                    253:         $this->index = 0;
                    254:     }
                    255: 
                    256:     /**
                    257:      * @return bool
                    258:      */
                    259:     public function valid()
                    260:     {
                    261:         return array_key_exists($this->index, $this->children);
                    262:     }
                    263: 
                    264:     /**
                    265:      * @return int
                    266:      */
                    267:     public function count()
                    268:     {
                    269:         return count($this->children);
                    270:     }
                    271: 
                    272:     /**
                    273:      * @return bool
                    274:      */
                    275:     public function hasChildren()
                    276:     {
                    277:         return !empty($this->children);
                    278:     }
                    279: 
                    280:     /**
                    281:      * @return \RecursiveArrayIterator
                    282:      */
                    283:     public function getChildren()
                    284:     {
                    285:         return new \RecursiveArrayIterator($this->children);
                    286:     }
                    287: }
                    288: 
                    289: $tree = new Tree();
                    290: $node1 = new Node('value1', 1);
                    291: $tree->getHead()->addChild($node1);
                    292: $node2 = new Node('value2', 2);
                    293: $node1->addChild($node2);
                    294: 
                    295: print_r($tree->findAll(2)->offsetGet(0));
                    296: --EXPECTF--
                    297: Node Object
                    298: (
                    299:     [children:protected] => Array
                    300:         (
                    301:         )
                    302: 
                    303:     [parent:protected] => Node Object
                    304:         (
                    305:             [children:protected] => Array
                    306:                 (
                    307:                     [0] => Node Object
                    308:  *RECURSION*
                    309:                 )
                    310: 
                    311:             [parent:protected] => Node Object
                    312:                 (
                    313:                     [children:protected] => Array
                    314:                         (
                    315:                             [0] => Node Object
                    316:  *RECURSION*
                    317:                         )
                    318: 
                    319:                     [parent:protected] => 
                    320:                     [data:protected] => HEAD
                    321:                     [uid:protected] => %s
                    322:                     [index:protected] => 0
                    323:                     [assureUnique:protected] => 
                    324:                     [storage:ArrayIterator:private] => Array
                    325:                         (
                    326:                         )
                    327: 
                    328:                 )
                    329: 
                    330:             [data:protected] => value1
                    331:             [uid:protected] => 1
                    332:             [index:protected] => 1
                    333:             [assureUnique:protected] => 
                    334:             [storage:ArrayIterator:private] => Array
                    335:                 (
                    336:                 )
                    337: 
                    338:         )
                    339: 
                    340:     [data:protected] => value2
                    341:     [uid:protected] => 2
                    342:     [index:protected] => 0
                    343:     [assureUnique:protected] => 
                    344:     [storage:ArrayIterator:private] => Array
                    345:         (
                    346:         )
                    347: 
                    348: )

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>