From 0d4e0c013ec088640580662822f6e37e65df8955 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. Closes GH-14849. --- NEWS | 4 ++++ ext/spl/spl_observer.c | 12 ++++++++---- ext/spl/tests/gh14639.phpt | 21 +++++++++++++++++++++ 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 ext/spl/tests/gh14639.phpt diff --git a/NEWS b/NEWS index f99079d04dbc8..9c6a61c624848 100644 --- a/NEWS +++ b/NEWS @@ -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) 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