mirror of
https://github.com/php/php-src.git
synced 2026-10-28 09:46:46 +08:00
Merge branch 'PHP-8.6'
* PHP-8.6: Fix GH-24264: Unwind/GracefulExit discarded in spl_iterators.c
This commit is contained in:
6 files changed
+145
-9
No files matched your search
+16
-9
@@ -244,6 +244,13 @@ static void spl_recursive_it_get_current_key(zend_object_iterator *iter, zval *k
|
||||
}
|
||||
}
|
||||
|
||||
static bool spl_can_catch_exception(zend_long flags)
|
||||
{
|
||||
return (flags & CIT_CATCH_GET_CHILD)
|
||||
&& !zend_is_unwind_exit(EG(exception))
|
||||
&& !zend_is_graceful_exit(EG(exception));
|
||||
}
|
||||
|
||||
static void spl_recursive_it_move_forward_ex(spl_recursive_it_object *object, zval *zthis)
|
||||
{
|
||||
zend_object_iterator *iterator;
|
||||
@@ -264,7 +271,7 @@ next_step:
|
||||
case RS_NEXT:
|
||||
iterator->funcs->move_forward(iterator);
|
||||
if (EG(exception)) {
|
||||
if (!(object->flags & RIT_CATCH_GET_CHILD)) {
|
||||
if (!spl_can_catch_exception(object->flags)) {
|
||||
return;
|
||||
} else {
|
||||
zend_clear_exception();
|
||||
@@ -301,7 +308,7 @@ next_step:
|
||||
zend_call_method_with_0_params(obj, ce, cache, "haschildren", &retval);
|
||||
}
|
||||
if (EG(exception)) {
|
||||
if (!(object->flags & RIT_CATCH_GET_CHILD)) {
|
||||
if (!spl_can_catch_exception(object->flags)) {
|
||||
object->iterators[object->level].state = RS_NEXT;
|
||||
return;
|
||||
} else {
|
||||
@@ -337,7 +344,7 @@ next_step:
|
||||
}
|
||||
object->iterators[object->level].state = RS_NEXT;
|
||||
if (EG(exception)) {
|
||||
if (!(object->flags & RIT_CATCH_GET_CHILD)) {
|
||||
if (!spl_can_catch_exception(object->flags)) {
|
||||
return;
|
||||
} else {
|
||||
zend_clear_exception();
|
||||
@@ -366,7 +373,7 @@ next_step:
|
||||
}
|
||||
|
||||
if (EG(exception)) {
|
||||
if (!(object->flags & RIT_CATCH_GET_CHILD)) {
|
||||
if (!spl_can_catch_exception(object->flags)) {
|
||||
return;
|
||||
} else {
|
||||
zend_clear_exception();
|
||||
@@ -410,7 +417,7 @@ next_step:
|
||||
if (object->beginChildren) {
|
||||
zend_call_known_function(object->beginChildren, Z_OBJ_P(zthis), object->ce, NULL, 0, NULL, NULL);
|
||||
if (EG(exception)) {
|
||||
if (!(object->flags & RIT_CATCH_GET_CHILD)) {
|
||||
if (!spl_can_catch_exception(object->flags)) {
|
||||
return;
|
||||
} else {
|
||||
zend_clear_exception();
|
||||
@@ -424,7 +431,7 @@ next_step:
|
||||
if (object->endChildren) {
|
||||
zend_call_known_function(object->endChildren, Z_OBJ_P(zthis), object->ce, NULL, 0, NULL, NULL);
|
||||
if (EG(exception)) {
|
||||
if (!(object->flags & RIT_CATCH_GET_CHILD)) {
|
||||
if (!spl_can_catch_exception(object->flags)) {
|
||||
return;
|
||||
} else {
|
||||
zend_clear_exception();
|
||||
@@ -2275,7 +2282,7 @@ static inline void spl_caching_it_next(spl_dual_it_object *intern)
|
||||
zend_call_method_with_0_params(Z_OBJ(intern->inner.zobject), intern->inner.ce, NULL, "haschildren", &retval);
|
||||
if (EG(exception)) {
|
||||
zval_ptr_dtor(&retval);
|
||||
if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) {
|
||||
if (spl_can_catch_exception(intern->u.caching.flags)) {
|
||||
zend_clear_exception();
|
||||
} else {
|
||||
return;
|
||||
@@ -2291,7 +2298,7 @@ static inline void spl_caching_it_next(spl_dual_it_object *intern)
|
||||
zend_call_method_with_0_params(Z_OBJ(intern->inner.zobject), intern->inner.ce, NULL, "getchildren", &args[0]);
|
||||
if (EG(exception)) {
|
||||
zval_ptr_dtor(&args[0]);
|
||||
if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) {
|
||||
if (spl_can_catch_exception(intern->u.caching.flags)) {
|
||||
zend_clear_exception();
|
||||
} else {
|
||||
return;
|
||||
@@ -2308,7 +2315,7 @@ static inline void spl_caching_it_next(spl_dual_it_object *intern)
|
||||
);
|
||||
zval_ptr_dtor(&args[0]);
|
||||
if (is_initialized == FAILURE) {
|
||||
if (intern->u.caching.flags & CIT_CATCH_GET_CHILD) {
|
||||
if (spl_can_catch_exception(intern->u.caching.flags)) {
|
||||
zend_clear_exception();
|
||||
} else {
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
GH-24264 (Unwind/GracefulExit discarded in spl_iterators.c): RecursiveIteratorIterator hasChildren()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class ReproIterator extends RecursiveArrayIterator {
|
||||
public function hasChildren(): bool {
|
||||
echo "exit\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
$it = new RecursiveIteratorIterator(
|
||||
new ReproIterator([1]),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY,
|
||||
RecursiveIteratorIterator::CATCH_GET_CHILD,
|
||||
);
|
||||
|
||||
foreach ($it as $_) {}
|
||||
|
||||
echo "Not reached\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
exit
|
||||
@@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
GH-24264 (Unwind/GracefulExit discarded in spl_iterators.c): RecursiveCachingIterator hasChildren()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class ReproIterator extends RecursiveArrayIterator {
|
||||
public function hasChildren(): bool {
|
||||
echo "exit\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
$it = new RecursiveCachingIterator(
|
||||
new ReproIterator([1]),
|
||||
CachingIterator::CATCH_GET_CHILD,
|
||||
);
|
||||
|
||||
foreach ($it as $_) {}
|
||||
|
||||
echo "Not reached\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
exit
|
||||
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
GH-24264 (Unwind/GracefulExit discarded in spl_iterators.c): RecursiveIteratorIterator getChildren()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class ReproIterator extends RecursiveArrayIterator {
|
||||
public function getChildren(): ?RecursiveArrayIterator {
|
||||
echo "exit\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
$it = new RecursiveIteratorIterator(
|
||||
new ReproIterator([[1]]),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY,
|
||||
RecursiveIteratorIterator::CATCH_GET_CHILD,
|
||||
);
|
||||
|
||||
foreach ($it as $_) {}
|
||||
|
||||
echo "Not reached\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
exit
|
||||
@@ -0,0 +1,23 @@
|
||||
--TEST--
|
||||
GH-24264 (Unwind/GracefulExit discarded in spl_iterators.c): RecursiveCachingIterator getChildren()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class ReproIterator extends RecursiveArrayIterator {
|
||||
public function getChildren(): ?RecursiveArrayIterator {
|
||||
echo "exit\n";
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
$it = new RecursiveCachingIterator(
|
||||
new ReproIterator([[1]]),
|
||||
CachingIterator::CATCH_GET_CHILD,
|
||||
);
|
||||
|
||||
foreach ($it as $_) {}
|
||||
|
||||
echo "Not reached\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
exit
|
||||
@@ -0,0 +1,35 @@
|
||||
--TEST--
|
||||
GH-24264 (Unwind/GracefulExit discarded in spl_iterators.c): destroyed fiber suspended in getChildren()
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class ReproIterator extends RecursiveArrayIterator {
|
||||
public function getChildren(): ?RecursiveArrayIterator {
|
||||
try {
|
||||
Fiber::suspend();
|
||||
} finally {
|
||||
echo "finally\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$fiber = new Fiber(function () {
|
||||
$it = new RecursiveIteratorIterator(
|
||||
new ReproIterator([[1], [2]]),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY,
|
||||
RecursiveIteratorIterator::CATCH_GET_CHILD,
|
||||
);
|
||||
|
||||
foreach ($it as $_) {}
|
||||
|
||||
echo "Not reached\n";
|
||||
});
|
||||
|
||||
$fiber->start();
|
||||
unset($fiber);
|
||||
|
||||
echo "Done\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
finally
|
||||
Done
|
||||
Reference in new issue
Block a user