Skip to content

Commit 5cacae8

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix GH-19094: Attaching class with no Iterator implementation to MultipleIterator causes crash
2 parents 28cd376 + 76b6b60 commit 5cacae8

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

ext/spl/spl_observer.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ PHPAPI zend_class_entry *spl_ce_SplObjectStorage;
3939
PHPAPI zend_class_entry *spl_ce_MultipleIterator;
4040

4141
static zend_object_handlers spl_handler_SplObjectStorage;
42+
static zend_object_handlers spl_handler_MultipleIterator;
4243

4344
/* Bit flags for marking internal functionality overridden by SplObjectStorage subclasses. */
4445
#define SOS_OVERRIDDEN_READ_DIMENSION 1
@@ -487,6 +488,20 @@ static void spl_object_storage_write_dimension(zend_object *object, zval *offset
487488
spl_object_storage_attach_handle(intern, Z_OBJ_P(offset), inf);
488489
}
489490

491+
static void spl_multiple_iterator_write_dimension(zend_object *object, zval *offset, zval *inf)
492+
{
493+
spl_SplObjectStorage *intern = spl_object_storage_from_obj(object);
494+
if (UNEXPECTED(offset == NULL || Z_TYPE_P(offset) != IS_OBJECT || (intern->flags & SOS_OVERRIDDEN_WRITE_DIMENSION))) {
495+
zend_std_write_dimension(object, offset, inf);
496+
return;
497+
}
498+
if (UNEXPECTED(!Z_OBJCE_P(offset)->iterator_funcs_ptr || !Z_OBJCE_P(offset)->iterator_funcs_ptr->zf_valid)) {
499+
zend_type_error("Can only attach objects that implement the Iterator interface");
500+
return;
501+
}
502+
spl_object_storage_attach_handle(intern, Z_OBJ_P(offset), inf);
503+
}
504+
490505
static void spl_object_storage_unset_dimension(zend_object *object, zval *offset)
491506
{
492507
spl_SplObjectStorage *intern = spl_object_storage_from_obj(object);
@@ -1389,9 +1404,13 @@ PHP_MINIT_FUNCTION(spl_observer)
13891404
spl_handler_SplObjectStorage.has_dimension = spl_object_storage_has_dimension;
13901405
spl_handler_SplObjectStorage.unset_dimension = spl_object_storage_unset_dimension;
13911406

1407+
memcpy(&spl_handler_MultipleIterator, &spl_handler_SplObjectStorage, sizeof(zend_object_handlers));
1408+
1409+
spl_handler_MultipleIterator.write_dimension = spl_multiple_iterator_write_dimension;
1410+
13921411
spl_ce_MultipleIterator = register_class_MultipleIterator(zend_ce_iterator);
13931412
spl_ce_MultipleIterator->create_object = spl_SplObjectStorage_new;
1394-
spl_ce_MultipleIterator->default_object_handlers = &spl_handler_SplObjectStorage;
1413+
spl_ce_MultipleIterator->default_object_handlers = &spl_handler_MultipleIterator;
13951414

13961415
return SUCCESS;
13971416
}

ext/spl/tests/gh19094.phpt

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
--TEST--
2+
GH-19094 (Attaching class with no Iterator implementation to MultipleIterator causes crash)
3+
--FILE--
4+
<?php
5+
6+
class MyIterator implements Iterator {
7+
public function valid(): bool {
8+
return false;
9+
}
10+
11+
public function current(): mixed {
12+
return null;
13+
}
14+
15+
public function key(): string {
16+
return "";
17+
}
18+
19+
public function next(): void {
20+
}
21+
22+
public function rewind(): void {
23+
}
24+
}
25+
26+
class MyAggregate implements IteratorAggregate {
27+
public function getIterator(): Traversable
28+
{
29+
throw new Error;
30+
}
31+
}
32+
33+
$cls = new MultipleIterator();
34+
$canary = new stdClass;
35+
try {
36+
$cls[$canary] = 1;
37+
} catch (TypeError $e) {
38+
echo $e->getMessage(), "\n";
39+
}
40+
try {
41+
$cls[new MyAggregate] = 1;
42+
} catch (TypeError $e) {
43+
echo $e->getMessage(), "\n";
44+
}
45+
$cls[new MyIterator] = 1;
46+
try {
47+
$cls->key();
48+
} catch (RuntimeException $e) {
49+
echo $e->getMessage(), "\n";
50+
}
51+
52+
?>
53+
--EXPECT--
54+
Can only attach objects that implement the Iterator interface
55+
Can only attach objects that implement the Iterator interface
56+
Called key() with non valid sub iterator

0 commit comments

Comments
 (0)