Bug #80965 [Opn->Nab]: A use after free bug in ext/spl/spl_dllist.c
| From: | nikic@php.net | Date: | Mon, 19 Apr 2021 12:46:47 +0000 |
| Subject: | Bug #80965 [Opn->Nab]: A use after free bug in ext/spl/spl_dllist.c | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-233507@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=80965&edit=1
ID: 80965
Updated by: nikic@php.net
Reported by: lylgood at foxmail dot com
Summary: A use after free bug in ext/spl/spl_dllist.c
-Status: Open
+Status: Not a bug
Type: Bug
Package: *Extensibility Functions
Operating System: All
PHP Version: master-Git-2021-04-18 (Git)
Block user comment: N
Private report: N
New Comment:
.
Previous Comments:
------------------------------------------------------------------------
[2021-04-19 12:43:43] nikic@php.net
This would only cause a use-after-free if some code setting traverse_pointer did not increment the
refcount. Otherwise this will only decrement the refcount, without freeing.
------------------------------------------------------------------------
[2021-04-18 07:03:14] lylgood at foxmail dot com
Description:
------------
File: ext/spl/spl_dllist.c
Bug Function: PHP_METHOD(SplDoublyLinkedList, offsetUnset)
In this function, element is obtained via spl_ptr_llist_offset() at line 834.
At line 863, the ref of element is decreased by one via SPL_LLIST_DELREF(element), if the refcount
of element is 0 now, the element will be freed.
But the freed element is still used at line 869 by SPL_LLIST_DELREF(element) which is a macro of
"if (!-- ((element)->data).u2.extra) { _efree((element)); }". It is a use after free.
If the freed memory of element is allocated by other objects before line 869,
then it is possible to fake structures to modify the refcount of element and cause an additional
double free.
Test script:
---------------
834: element = spl_ptr_llist_offset(intern->llist, index, intern->flags &
SPL_DLLIST_IT_LIFO);
...
if (intern->traverse_pointer == element) {
863: SPL_LLIST_DELREF(element); // element First freed here!
intern->traverse_pointer = NULL;
}
zval_ptr_dtor(&element->data);
ZVAL_UNDEF(&element->data);
869: SPL_LLIST_DELREF(element) // Freed element is used and could be freed again!
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=80965&edit=1