Skip to content

Commit 76b6b60

Browse files
committed
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3: Fix GH-19094: Attaching class with no Iterator implementation to MultipleIterator causes crash
2 parents de7a212 + 7147226 commit 76b6b60

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ PHP NEWS
5454
on object destruction). (nielsdos)
5555
. Fix memory leak when URL parsing fails in redirect. (Girgias)
5656

57+
- SPL:
58+
. Fixed bug GH-19094 (Attaching class with no Iterator implementation to
59+
MultipleIterator causes crash). (nielsdos)
60+
5761
- Standard:
5862
. Fix misleading errors in printf(). (nielsdos)
5963
. Fix RCN violations in array functions. (nielsdos)

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
@@ -488,6 +489,20 @@ static void spl_object_storage_write_dimension(zend_object *object, zval *offset
488489
spl_object_storage_attach_handle(intern, Z_OBJ_P(offset), inf);
489490
}
490491

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

1408+
memcpy(&spl_handler_MultipleIterator, &spl_handler_SplObjectStorage, sizeof(zend_object_handlers));
1409+
1410+
spl_handler_MultipleIterator.write_dimension = spl_multiple_iterator_write_dimension;
1411+
13931412
spl_ce_MultipleIterator = register_class_MultipleIterator(zend_ce_iterator);
13941413
spl_ce_MultipleIterator->create_object = spl_SplObjectStorage_new;
1395-
spl_ce_MultipleIterator->default_object_handlers = &spl_handler_SplObjectStorage;
1414+
spl_ce_MultipleIterator->default_object_handlers = &spl_handler_MultipleIterator;
13961415

13971416
return SUCCESS;
13981417
}

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)