Skip to content

Commit 29b2522

Browse files
committed
Merge branch 'PHP-5.4' of https://git.php.net/repository/php-src into PHP-5.4
* 'PHP-5.4' of https://git.php.net/repository/php-src: Upper section name Fixed bug #65328 (Segfault when getting SplStack object Value)
2 parents 96a53f6 + 5150929 commit 29b2522

File tree

3 files changed

+352
-1
lines changed

3 files changed

+352
-1
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ PHP NEWS
1414
. Fixed bug #50308 (session id not appended properly for empty anchor tags).
1515
(Arpad)
1616

17+
- SPL:
18+
. Fixed bug #65328 (Segfault when getting SplStack object Value). (Laruence)
19+
1720
- Phar:
1821
. Fixed bug #65028 (Phar::buildFromDirectory creates corrupt archives for
1922
some specific contents). (Stas)

ext/spl/spl_array.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1658,7 +1658,7 @@ SPL_METHOD(Array, getChildren)
16581658
return;
16591659
}
16601660
if (instanceof_function(Z_OBJCE_PP(entry), Z_OBJCE_P(getThis()) TSRMLS_CC)) {
1661-
RETURN_ZVAL(*entry, 0, 0);
1661+
RETURN_ZVAL(*entry, 1, 0);
16621662
}
16631663
}
16641664

ext/spl/tests/bug65328.phpt

Lines changed: 348 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
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+
)

0 commit comments

Comments
 (0)