From f04517a2b55c17616b80729110f5ae03006ff6dd Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 6 Jul 2024 22:46:27 +0200 Subject: [PATCH] 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. --- ext/spl/spl_observer.c | 12 ++++++++---- ext/spl/tests/gh14639.phpt | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 ext/spl/tests/gh14639.phpt diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 339bd0b6e5d22..21b19cffa38ad 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -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) /* {{{ */ @@ -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; } /* }}} */ diff --git a/ext/spl/tests/gh14639.phpt b/ext/spl/tests/gh14639.phpt new file mode 100644 index 0000000000000..1b6f621d27bd3 --- /dev/null +++ b/ext/spl/tests/gh14639.phpt @@ -0,0 +1,21 @@ +--TEST-- +GH-14639 (Member access within null pointer in ext/spl/spl_observer.c) +--INI-- +memory_limit=2M +--SKIPIF-- + +--FILE-- + 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