-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Use after free in SplDoublyLinkedList #16464
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Thanks for the report! Reproduces for me. Likely this can be fixed in a similar way as #16346 |
I think we can just delay the destructor call. diff --git a/Zend/tests/gh16464.phpt b/Zend/tests/gh16464.phpt
new file mode 100644
index 0000000000..75f34fc250
--- /dev/null
+++ b/Zend/tests/gh16464.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Use-after-free in SplDoublyLinkedList::offsetSet() when modifying list in destructor of overwritten object
+--FILE--
+<?php
+
+class C {
+ public $a;
+
+ function __destruct() {
+ global $list;
+ var_dump($list->pop());
+ }
+}
+
+$list = new SplDoublyLinkedList;
+$list->add(0, new C);
+$list[0] = 42;
+var_dump($list);
+
+?>
+--EXPECTF--
+int(42)
+object(SplDoublyLinkedList)#%d (2) {
+ ["flags":"SplDoublyLinkedList":private]=>
+ int(0)
+ ["dllist":"SplDoublyLinkedList":private]=>
+ array(0) {
+ }
+}
diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c
index 186b9a34c7..6592efc4e5 100644
--- a/ext/spl/spl_dllist.c
+++ b/ext/spl/spl_dllist.c
@@ -737,8 +737,10 @@ PHP_METHOD(SplDoublyLinkedList, offsetSet)
if (element != NULL) {
/* the element is replaced, delref the old one as in
* SplDoublyLinkedList::pop() */
- zval_ptr_dtor(&element->data);
+ zval garbage;
+ ZVAL_COPY_VALUE(&garbage, &element->data);
ZVAL_COPY(&element->data, value);
+ zval_ptr_dtor(&garbage);
} else {
zval_ptr_dtor(value);
zend_argument_error(spl_ce_OutOfRangeException, 1, "is an invalid offset"); |
I hadn't yet looked at the implementation. Indeed that's easier and looks right. |
Indeed, this only works here because we may fully delay the destructor, and there are no other possible side-effects. I'll open a PR. |
Write to the new offset before calling the destructor of the previous value. Fixes phpGH-16464
Write to the new offset before calling the destructor of the previous value. Fixes phpGH-16464
Description
The following code:
Resulted in this output:
But I expected this output instead:
PHP Version
PHP 8.5.0-dev
Operating System
No response
The text was updated successfully, but these errors were encountered: