Skip to content

Commit 1a2b370

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Fix uaf in SplDoublyLinkedList::offsetSet()
2 parents ec15210 + d15e227 commit 1a2b370

File tree

2 files changed

+32
-1
lines changed

2 files changed

+32
-1
lines changed

ext/spl/spl_dllist.c

+3-1
Original file line numberDiff line numberDiff line change
@@ -726,8 +726,10 @@ PHP_METHOD(SplDoublyLinkedList, offsetSet)
726726
if (element != NULL) {
727727
/* the element is replaced, delref the old one as in
728728
* SplDoublyLinkedList::pop() */
729-
zval_ptr_dtor(&element->data);
729+
zval garbage;
730+
ZVAL_COPY_VALUE(&garbage, &element->data);
730731
ZVAL_COPY(&element->data, value);
732+
zval_ptr_dtor(&garbage);
731733
} else {
732734
zval_ptr_dtor(value);
733735
zend_argument_error(spl_ce_OutOfRangeException, 1, "is an invalid offset");

ext/spl/tests/gh16464.phpt

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
GH-16464: Use-after-free in SplDoublyLinkedList::offsetSet() when modifying list in destructor of overwritten object
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public $a;
8+
9+
function __destruct() {
10+
global $list;
11+
var_dump($list->pop());
12+
}
13+
}
14+
15+
$list = new SplDoublyLinkedList;
16+
$list->add(0, new C);
17+
$list[0] = 42;
18+
var_dump($list);
19+
20+
?>
21+
--EXPECTF--
22+
int(42)
23+
object(SplDoublyLinkedList)#%d (2) {
24+
["flags":"SplDoublyLinkedList":private]=>
25+
int(0)
26+
["dllist":"SplDoublyLinkedList":private]=>
27+
array(0) {
28+
}
29+
}

0 commit comments

Comments
 (0)