diff --git a/NEWS b/NEWS index 5e97866b991..3ed4cc4cf7b 100644 --- a/NEWS +++ b/NEWS @@ -18,6 +18,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) - SysVShm: . Fixed bug GH-16591 (Assertion error in shm_put_var). (nielsdos, cmb) diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index 74ae655b220..5a78db2921a 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -41,10 +41,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)++ @@ -1013,8 +1016,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:{}"