Skip to content

Commit 0d4e0c0

Browse files
committed
Fix GH-14639: Member access within null pointer in ext/spl/spl_observer.c
`spl_object_storage_attach_handle` creates an entry already, but only fills it in at the end with `spl_object_storage_create_element` which allocates memory. In this case the allocation fails and we're left with a NULL slot. Doing the allocation first isn't an option because we want to check whether the slot is occupied before allocating memory. The simplest solution is to set the entry to NULL and check for a NULL pointer upon destruction. Closes GH-14849.
1 parent 2375187 commit 0d4e0c0

File tree

3 files changed

+33
-4
lines changed

3 files changed

+33
-4
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ PHP NEWS
4040
. Fixed bug GH-14638 (null dereference after XML parsing failure).
4141
(David Carlier)
4242

43+
- SPL:
44+
. Fixed bug GH-14639 (Member access within null pointer in
45+
ext/spl/spl_observer.c). (nielsdos)
46+
4347
- Standard:
4448
. Fix 32-bit wordwrap test failures. (orlitzky)
4549
. Fixed bug GH-14774 (time_sleep_until overflow). (David Carlier)

ext/spl/spl_observer.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,11 @@ static void spl_object_storage_free_hash(spl_SplObjectStorage *intern, zend_hash
118118
static void spl_object_storage_dtor(zval *element) /* {{{ */
119119
{
120120
spl_SplObjectStorageElement *el = Z_PTR_P(element);
121-
zend_object_release(el->obj);
122-
zval_ptr_dtor(&el->inf);
123-
efree(el);
121+
if (el) {
122+
zend_object_release(el->obj);
123+
zval_ptr_dtor(&el->inf);
124+
efree(el);
125+
}
124126
} /* }}} */
125127

126128
static spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, zend_hash_key *key) /* {{{ */
@@ -168,8 +170,10 @@ static spl_SplObjectStorageElement *spl_object_storage_attach_handle(spl_SplObje
168170
return pelement;
169171
}
170172

173+
/* NULL initialization necessary because `spl_object_storage_create_element` could bail out due to OOM. */
174+
ZVAL_PTR(entry_zv, NULL);
171175
pelement = spl_object_storage_create_element(obj, inf);
172-
ZVAL_PTR(entry_zv, pelement);
176+
Z_PTR_P(entry_zv) = pelement;
173177
return pelement;
174178
} /* }}} */
175179

ext/spl/tests/gh14639.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
GH-14639 (Member access within null pointer in ext/spl/spl_observer.c)
3+
--INI--
4+
memory_limit=2M
5+
--SKIPIF--
6+
<?php
7+
if (getenv("USE_ZEND_ALLOC") === "0") {
8+
die("skip Zend MM disabled");
9+
}
10+
?>
11+
--FILE--
12+
<?php
13+
$b = new SplObjectStorage();
14+
for ($i = 10000; $i > 0; $i--) {
15+
$object = new StdClass();
16+
$object->a = str_repeat("a", 2);
17+
$b->attach($object);
18+
}
19+
?>
20+
--EXPECTF--
21+
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d

0 commit comments

Comments
 (0)