From 8f60309a78e5c30b7713b820258676ef5ce19786 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sat, 26 Oct 2024 12:31:12 +0200 Subject: [PATCH] Fix GH-16589: UAF in SplDoublyLinked->serialize() Closes GH-16611. --- NEWS | 1 + ext/spl/spl_dllist.c | 9 ++++++++- ext/spl/tests/gh16589.phpt | 23 +++++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 ext/spl/tests/gh16589.phpt diff --git a/NEWS b/NEWS index f373d962e41..08db61d58eb 100644 --- a/NEWS +++ b/NEWS @@ -105,6 +105,7 @@ PHP NEWS . Fixed bug GH-16588 (UAF in Observer->serialize). (nielsdos) . Fix GH-16477 (Segmentation fault when calling __debugInfo() after failed SplFileObject::__constructor). (Girgias) + . Fixed bug GH-16589 (UAF in SplDoublyLinked->serialize()). (nielsdos) - Standard: . Fixed bug GH-16293 (Failed assertion when throwing in assert() callback with diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 6592efc4e5e..612fe2a7ed9 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -44,10 +44,13 @@ PHPAPI zend_class_entry *spl_ce_SplStack; efree(elem); \ } -#define SPL_LLIST_CHECK_DELREF(elem) if ((elem) && !--SPL_LLIST_RC(elem)) { \ +#define SPL_LLIST_CHECK_DELREF_EX(elem, on_free) if ((elem) && !--SPL_LLIST_RC(elem)) { \ efree(elem); \ + on_free \ } +#define SPL_LLIST_CHECK_DELREF(elem) SPL_LLIST_CHECK_DELREF_EX(elem, ;) + #define SPL_LLIST_ADDREF(elem) SPL_LLIST_RC(elem)++ #define SPL_LLIST_CHECK_ADDREF(elem) if (elem) SPL_LLIST_RC(elem)++ @@ -1024,8 +1027,12 @@ PHP_METHOD(SplDoublyLinkedList, serialize) smart_str_appendc(&buf, ':'); next = current->next; + SPL_LLIST_CHECK_ADDREF(next); + php_var_serialize(&buf, ¤t->data, &var_hash); + SPL_LLIST_CHECK_DELREF_EX(next, break;); + current = next; } diff --git a/ext/spl/tests/gh16589.phpt b/ext/spl/tests/gh16589.phpt new file mode 100644 index 00000000000..7b1452e37a4 --- /dev/null +++ b/ext/spl/tests/gh16589.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-16589 (UAF in SplDoublyLinked->serialize()) +--CREDITS-- +chibinz +--FILE-- +pop(); + return []; + } +} + +$list = new SplDoublyLinkedList; +$list->add(0, new C); +$list->add(1, 1); +var_dump($list->serialize()); + +?> +--EXPECT-- +string(17) "i:0;:O:1:"C":0:{}"