diff --git a/NEWS b/NEWS index c046b95db2e..1aaca5dc75b 100644 --- a/NEWS +++ b/NEWS @@ -112,6 +112,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 9ae72881aab..dd3f691df79 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)++ @@ -1023,8 +1026,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:{}"