Skip to content

Commit 39b8d5c

Browse files
committed
Fix GH-13612: Corrupted memory in destructor with weak references
Inside `zend_object_std_dtor` the weakrefs are notified after the destruction of properties already took place. In this test case, the destructor of an anon class will be invoked due to the property destruction. That class has a weak reference to its parent. This means that the destructor can access parent properties that already have been destroyed, resulting in a UAF. Fix this by notifying the weakrefs at the start of the object's destruction. Closes GH-13613.
1 parent e3f0d03 commit 39b8d5c

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.2.18
44

5+
- Core:
6+
. Fixed bug GH-13612 (Corrupted memory in destructor with weak references).
7+
(nielsdos)
8+
59
- Gettext:
610
- Fixed sigabrt raised with dcgettext/dcngettext calls with gettext 0.22.5
711
with category set to LC_ALL. (David Carlier)

Zend/tests/weakrefs/gh13612.phpt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
GH-13612 (Corrupted memory in destructor with weak references)
3+
--FILE--
4+
<?php
5+
6+
class WeakAnalysingMapRepro
7+
{
8+
public array $destroyed = [];
9+
public array $ownerDestructorHandlers = [];
10+
11+
public function __construct()
12+
{
13+
$handler = new class($this) {
14+
private \WeakReference $weakAnalysingMap;
15+
16+
public function __construct(WeakAnalysingMapRepro $analysingMap)
17+
{
18+
$this->weakAnalysingMap = \WeakReference::create($analysingMap);
19+
}
20+
21+
public function __destruct()
22+
{
23+
var_dump($this->weakAnalysingMap->get());
24+
}
25+
};
26+
27+
$this->destroyed[] = 1;
28+
$this->ownerDestructorHandlers[] = $handler;
29+
}
30+
}
31+
32+
new WeakAnalysingMapRepro();
33+
34+
echo "Done\n";
35+
36+
?>
37+
--EXPECT--
38+
NULL
39+
Done

Zend/zend_objects.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ ZEND_API void zend_object_std_dtor(zend_object *object)
4747
{
4848
zval *p, *end;
4949

50+
if (UNEXPECTED(GC_FLAGS(object) & IS_OBJ_WEAKLY_REFERENCED)) {
51+
zend_weakrefs_notify(object);
52+
}
53+
5054
if (object->properties) {
5155
if (EXPECTED(!(GC_FLAGS(object->properties) & IS_ARRAY_IMMUTABLE))) {
5256
if (EXPECTED(GC_DELREF(object->properties) == 0)
@@ -85,10 +89,6 @@ ZEND_API void zend_object_std_dtor(zend_object *object)
8589
FREE_HASHTABLE(guards);
8690
}
8791
}
88-
89-
if (UNEXPECTED(GC_FLAGS(object) & IS_OBJ_WEAKLY_REFERENCED)) {
90-
zend_weakrefs_notify(object);
91-
}
9292
}
9393

9494
ZEND_API void zend_objects_destroy_object(zend_object *object)

0 commit comments

Comments
 (0)