Skip to content

Commit

Permalink
Fix GH-14639: Member access within null pointer in ext/spl/spl_observ…
Browse files Browse the repository at this point in the history
…er.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.
  • Loading branch information
nielsdos committed Jul 6, 2024
1 parent 2375187 commit 0d4e0c0
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 4 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ PHP NEWS
. Fixed bug GH-14638 (null dereference after XML parsing failure).
(David Carlier)

- SPL:
. Fixed bug GH-14639 (Member access within null pointer in
ext/spl/spl_observer.c). (nielsdos)

- Standard:
. Fix 32-bit wordwrap test failures. (orlitzky)
. Fixed bug GH-14774 (time_sleep_until overflow). (David Carlier)
Expand Down
12 changes: 8 additions & 4 deletions ext/spl/spl_observer.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,11 @@ static void spl_object_storage_free_hash(spl_SplObjectStorage *intern, zend_hash
static void spl_object_storage_dtor(zval *element) /* {{{ */
{
spl_SplObjectStorageElement *el = Z_PTR_P(element);
zend_object_release(el->obj);
zval_ptr_dtor(&el->inf);
efree(el);
if (el) {
zend_object_release(el->obj);
zval_ptr_dtor(&el->inf);
efree(el);
}
} /* }}} */

static spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, zend_hash_key *key) /* {{{ */
Expand Down Expand Up @@ -168,8 +170,10 @@ static spl_SplObjectStorageElement *spl_object_storage_attach_handle(spl_SplObje
return pelement;
}

/* NULL initialization necessary because `spl_object_storage_create_element` could bail out due to OOM. */
ZVAL_PTR(entry_zv, NULL);
pelement = spl_object_storage_create_element(obj, inf);
ZVAL_PTR(entry_zv, pelement);
Z_PTR_P(entry_zv) = pelement;
return pelement;
} /* }}} */

Expand Down
21 changes: 21 additions & 0 deletions ext/spl/tests/gh14639.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
GH-14639 (Member access within null pointer in ext/spl/spl_observer.c)
--INI--
memory_limit=2M
--SKIPIF--
<?php
if (getenv("USE_ZEND_ALLOC") === "0") {
die("skip Zend MM disabled");
}
?>
--FILE--
<?php
$b = new SplObjectStorage();
for ($i = 10000; $i > 0; $i--) {
$object = new StdClass();
$object->a = str_repeat("a", 2);
$b->attach($object);
}
?>
--EXPECTF--
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %s on line %d

0 comments on commit 0d4e0c0

Please sign in to comment.