mirror of
https://github.com/php/php-src.git
synced 2025-08-16 14:08:47 +02:00
Merge branch 'PHP-8.4'
* PHP-8.4: Fix GH-19094: Attaching class with no Iterator implementation to MultipleIterator causes crash
This commit is contained in:
commit
5cacae8f29
2 changed files with 76 additions and 1 deletions
|
@ -39,6 +39,7 @@ PHPAPI zend_class_entry *spl_ce_SplObjectStorage;
|
||||||
PHPAPI zend_class_entry *spl_ce_MultipleIterator;
|
PHPAPI zend_class_entry *spl_ce_MultipleIterator;
|
||||||
|
|
||||||
static zend_object_handlers spl_handler_SplObjectStorage;
|
static zend_object_handlers spl_handler_SplObjectStorage;
|
||||||
|
static zend_object_handlers spl_handler_MultipleIterator;
|
||||||
|
|
||||||
/* Bit flags for marking internal functionality overridden by SplObjectStorage subclasses. */
|
/* Bit flags for marking internal functionality overridden by SplObjectStorage subclasses. */
|
||||||
#define SOS_OVERRIDDEN_READ_DIMENSION 1
|
#define SOS_OVERRIDDEN_READ_DIMENSION 1
|
||||||
|
@ -487,6 +488,20 @@ static void spl_object_storage_write_dimension(zend_object *object, zval *offset
|
||||||
spl_object_storage_attach_handle(intern, Z_OBJ_P(offset), inf);
|
spl_object_storage_attach_handle(intern, Z_OBJ_P(offset), inf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void spl_multiple_iterator_write_dimension(zend_object *object, zval *offset, zval *inf)
|
||||||
|
{
|
||||||
|
spl_SplObjectStorage *intern = spl_object_storage_from_obj(object);
|
||||||
|
if (UNEXPECTED(offset == NULL || Z_TYPE_P(offset) != IS_OBJECT || (intern->flags & SOS_OVERRIDDEN_WRITE_DIMENSION))) {
|
||||||
|
zend_std_write_dimension(object, offset, inf);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (UNEXPECTED(!Z_OBJCE_P(offset)->iterator_funcs_ptr || !Z_OBJCE_P(offset)->iterator_funcs_ptr->zf_valid)) {
|
||||||
|
zend_type_error("Can only attach objects that implement the Iterator interface");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
spl_object_storage_attach_handle(intern, Z_OBJ_P(offset), inf);
|
||||||
|
}
|
||||||
|
|
||||||
static void spl_object_storage_unset_dimension(zend_object *object, zval *offset)
|
static void spl_object_storage_unset_dimension(zend_object *object, zval *offset)
|
||||||
{
|
{
|
||||||
spl_SplObjectStorage *intern = spl_object_storage_from_obj(object);
|
spl_SplObjectStorage *intern = spl_object_storage_from_obj(object);
|
||||||
|
@ -1389,9 +1404,13 @@ PHP_MINIT_FUNCTION(spl_observer)
|
||||||
spl_handler_SplObjectStorage.has_dimension = spl_object_storage_has_dimension;
|
spl_handler_SplObjectStorage.has_dimension = spl_object_storage_has_dimension;
|
||||||
spl_handler_SplObjectStorage.unset_dimension = spl_object_storage_unset_dimension;
|
spl_handler_SplObjectStorage.unset_dimension = spl_object_storage_unset_dimension;
|
||||||
|
|
||||||
|
memcpy(&spl_handler_MultipleIterator, &spl_handler_SplObjectStorage, sizeof(zend_object_handlers));
|
||||||
|
|
||||||
|
spl_handler_MultipleIterator.write_dimension = spl_multiple_iterator_write_dimension;
|
||||||
|
|
||||||
spl_ce_MultipleIterator = register_class_MultipleIterator(zend_ce_iterator);
|
spl_ce_MultipleIterator = register_class_MultipleIterator(zend_ce_iterator);
|
||||||
spl_ce_MultipleIterator->create_object = spl_SplObjectStorage_new;
|
spl_ce_MultipleIterator->create_object = spl_SplObjectStorage_new;
|
||||||
spl_ce_MultipleIterator->default_object_handlers = &spl_handler_SplObjectStorage;
|
spl_ce_MultipleIterator->default_object_handlers = &spl_handler_MultipleIterator;
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
56
ext/spl/tests/gh19094.phpt
Normal file
56
ext/spl/tests/gh19094.phpt
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
--TEST--
|
||||||
|
GH-19094 (Attaching class with no Iterator implementation to MultipleIterator causes crash)
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class MyIterator implements Iterator {
|
||||||
|
public function valid(): bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function current(): mixed {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function key(): string {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function next(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rewind(): void {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyAggregate implements IteratorAggregate {
|
||||||
|
public function getIterator(): Traversable
|
||||||
|
{
|
||||||
|
throw new Error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$cls = new MultipleIterator();
|
||||||
|
$canary = new stdClass;
|
||||||
|
try {
|
||||||
|
$cls[$canary] = 1;
|
||||||
|
} catch (TypeError $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$cls[new MyAggregate] = 1;
|
||||||
|
} catch (TypeError $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
$cls[new MyIterator] = 1;
|
||||||
|
try {
|
||||||
|
$cls->key();
|
||||||
|
} catch (RuntimeException $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Can only attach objects that implement the Iterator interface
|
||||||
|
Can only attach objects that implement the Iterator interface
|
||||||
|
Called key() with non valid sub iterator
|
Loading…
Add table
Add a link
Reference in a new issue