Skip to content

Commit 6c2e97b

Browse files
committed
Fix use-after-free of object through __isset() and globals
Fixes GH-18845
1 parent 2e2494f commit 6c2e97b

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

Zend/tests/gh18845.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
GH-18845: Use-after-free of object through __isset() and globals
3+
--FILE--
4+
<?php
5+
6+
#[AllowDynamicProperties]
7+
class C {
8+
public $dummy;
9+
public function __isset($x) {
10+
$GLOBALS['c'] = null;
11+
return true;
12+
}
13+
}
14+
15+
$c = new C;
16+
var_dump($c->prop ?? 1);
17+
18+
$r = new ReflectionClass(C::class);
19+
$c = $r->newLazyProxy(function () {
20+
throw new Exception('Not reached');
21+
});
22+
var_dump($c->prop ?? 1);
23+
24+
?>
25+
--EXPECT--
26+
int(1)
27+
int(1)

Zend/zend_object_handlers.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,7 +905,13 @@ ZEND_API zval *zend_std_read_property(zend_object *zobj, zend_string *name, int
905905
if (zobj->ce->__get && !((*guard) & IN_GET)) {
906906
goto call_getter;
907907
}
908+
909+
bool obj_is_freed = GC_REFCOUNT(zobj) == 1;
908910
OBJ_RELEASE(zobj);
911+
if (UNEXPECTED(obj_is_freed)) {
912+
retval = &EG(uninitialized_zval);
913+
goto exit;
914+
}
909915
} else if (zobj->ce->__get && !((*guard) & IN_GET)) {
910916
goto call_getter_addref;
911917
}

0 commit comments

Comments
 (0)