Skip to content

Commit 456c632

Browse files
committed
review
1 parent 7b3a1f1 commit 456c632

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

ext/spl/spl_array.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ PHPAPI zend_class_entry *spl_ce_ArrayObject;
4040

4141
typedef struct _spl_array_object {
4242
zval array;
43+
HashTable *sentinel_array;
4344
uint32_t ht_iter;
4445
int ar_flags;
4546
unsigned char nApplyCount;
@@ -79,11 +80,14 @@ static inline HashTable **spl_array_get_hash_table_ptr(spl_array_object* intern)
7980
if (UNEXPECTED(zend_lazy_object_must_init(obj))) {
8081
obj = zend_lazy_object_init(obj);
8182
if (UNEXPECTED(!obj)) {
82-
zval_ptr_dtor(&intern->array);
83-
ZVAL_ARR(&intern->array, zend_new_array(0));
84-
return &Z_ARRVAL(intern->array);
83+
if (!intern->sentinel_array) {
84+
intern->sentinel_array = zend_new_array(0);
85+
}
86+
return &intern->sentinel_array;
8587
}
8688
}
89+
/* should no longer be lazy */
90+
ZEND_ASSERT(!zend_lazy_object_must_init(obj));
8791
/* rebuild properties */
8892
zend_std_get_properties_ex(obj);
8993
if (GC_REFCOUNT(obj->properties) > 1) {
@@ -139,6 +143,10 @@ static void spl_array_object_free_storage(zend_object *object)
139143
zend_hash_iterator_del(intern->ht_iter);
140144
}
141145

146+
if (UNEXPECTED(intern->sentinel_array)) {
147+
zend_array_release(intern->sentinel_array);
148+
}
149+
142150
zend_object_std_dtor(&intern->std);
143151

144152
zval_ptr_dtor(&intern->array);
@@ -499,6 +507,9 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec
499507
uint32_t refcount = 0;
500508
if (!offset || Z_TYPE_P(offset) == IS_NULL) {
501509
ht = spl_array_get_hash_table(intern);
510+
if (UNEXPECTED(ht == intern->sentinel_array)) {
511+
return;
512+
}
502513
refcount = spl_array_set_refcount(intern->is_child, ht, 1);
503514
zend_hash_next_index_insert(ht, value);
504515

@@ -515,6 +526,10 @@ static void spl_array_write_dimension_ex(int check_inherited, zend_object *objec
515526
}
516527

517528
ht = spl_array_get_hash_table(intern);
529+
if (UNEXPECTED(ht == intern->sentinel_array)) {
530+
spl_hash_key_release(&key);
531+
return;
532+
}
518533
refcount = spl_array_set_refcount(intern->is_child, ht, 1);
519534
if (key.key) {
520535
zend_hash_update_ind(ht, key.key, value);

ext/spl/tests/gh15833_2.phpt

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,33 @@ class C {
99
}
1010
$reflector = new ReflectionClass(C::class);
1111
$obj = $reflector->newLazyProxy(function ($obj) {
12-
throw new Error('foo');
12+
static $counter = 0;
13+
throw new Error('nope ' . ($counter++));
1314
});
1415
$recursiveArrayIterator = new RecursiveArrayIterator($obj);
1516
try {
1617
var_dump($recursiveArrayIterator->current());
1718
} catch (Error $e) {
1819
echo $e->getMessage(), "\n";
1920
}
20-
var_dump($recursiveArrayIterator->current());
21-
$recursiveArrayIterator->next();
22-
var_dump($recursiveArrayIterator->current());
21+
try {
22+
var_dump($recursiveArrayIterator->current());
23+
} catch (Error $e) {
24+
echo $e->getMessage(), "\n";
25+
}
26+
try {
27+
$recursiveArrayIterator->next();
28+
} catch (Error $e) {
29+
echo $e->getMessage(), "\n";
30+
}
31+
try {
32+
var_dump($recursiveArrayIterator->current());
33+
} catch (Error $e) {
34+
echo $e->getMessage(), "\n";
35+
}
2336
?>
2437
--EXPECT--
25-
foo
26-
NULL
27-
NULL
38+
nope 0
39+
nope 1
40+
nope 2
41+
nope 3

0 commit comments

Comments
 (0)