Description
The following code:
<?php
class A {
public $a;
public int $b;
public int $c = 42;
public int $d;
public int $e;
public function __construct() {
unset($this->e);
}
}
class B {
public int $f;
public int $g;
public int $h;
public function __construct() {
unset($this->g);
unset($this->h);
}
public function&__isset($name) {
return $name === 'h';
}
public function __get($name) {}
}
class C {
public int $i;
public int $j;
public int $k;
public function __construct() {
unset($this->j);
unset($this->k);
}
public function __get($name) {}
}
function test($class) {
$rc = new ReflectionClass($class);
foreach ($rc->getProperties() as $rp) {
echo $rp->getName() . ' from global: ';
var_dump($rp->isReadable(null, new $class));
}
}
test('A');
test('B');
test('C');
Resulted in this output:
php-fuzz-execute: /home/kid/php_newest/Zend/zend_vm_execute.h:2161: const zend_op *ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER(zend_execute_data *, const zend_op *): Assertion `(call->func->common.fn_flags & (1 << 12)) ? (zval_get_type(&(*(ret))) == 10) : !(zval_get_type(&(*(ret))) == 10)' failed.
==69783== ERROR: libFuzzer: deadly signal
#0 0x5bf1954dd715 in __sanitizer_print_stack_trace (/home/kid/php_newest/sapi/fuzzer/php-fuzz-execute+0x38dd715) (BuildId: 0d5597bf0ebd2525add5014f4baf69af768a9c63)
#1 0x5bf19543722c in fuzzer::PrintStackTrace() (/home/kid/php_newest/sapi/fuzzer/php-fuzz-execute+0x383722c) (BuildId: 0d5597bf0ebd2525add5014f4baf69af768a9c63)
#2 0x5bf19541d2b7 in fuzzer::Fuzzer::CrashCallback() (/home/kid/php_newest/sapi/fuzzer/php-fuzz-execute+0x381d2b7) (BuildId: 0d5597bf0ebd2525add5014f4baf69af768a9c63)
#3 0x78909e84532f (/lib/x86_64-linux-gnu/libc.so.6+0x4532f) (BuildId: 8e9fd827446c24067541ac5390e6f527fb5947bb)
#4 0x78909e89eb2b in __pthread_kill_implementation nptl/pthread_kill.c:43:17
#5 0x78909e89eb2b in __pthread_kill_internal nptl/pthread_kill.c:78:10
#6 0x78909e89eb2b in pthread_kill nptl/pthread_kill.c:89:10
#7 0x78909e84527d in raise signal/../sysdeps/posix/raise.c:26:13
#8 0x78909e8288fe in abort stdlib/abort.c:79:7
#9 0x78909e82881a in __assert_fail_base assert/assert.c:96:3
#10 0x78909e83b516 in __assert_fail assert/assert.c:105:3
#11 0x5bf19a8ebdbe in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER /home/kid/php_newest/Zend/zend_vm_execute.h:2160:4
#12 0x5bf19b6e0920 in fuzzer_execute_ex /home/kid/php_newest/sapi/fuzzer/fuzzer-execute-common.h:65:12
#13 0x5bf19a8e4e15 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER /home/kid/php_newest/Zend/zend_vm_execute.h:1990:4
#14 0x5bf19b6e0920 in fuzzer_execute_ex /home/kid/php_newest/sapi/fuzzer/fuzzer-execute-common.h:65:12
#15 0x5bf19a5696cf in zend_execute /home/kid/php_newest/Zend/zend_vm_execute.h:115586:2
#16 0x5bf19b6e4136 in fuzzer_do_request_from_buffer /home/kid/php_newest/sapi/fuzzer/fuzzer-sapi.c:293:5
#17 0x5bf19b6e03b9 in LLVMFuzzerTestOneInput /home/kid/php_newest/sapi/fuzzer/fuzzer-execute.c:25:2
This seems to happen because ReflectionProperty::isReadable() forwards the result of __isset() directly without validation, so a by-reference return can leak into a non-reference return slot.
PHP Version
find in the commit c417deaf0f6e0a44da2315dd631b2f918a295782
and it still crashed in the latest commit
Operating System
Ubuntu 24.04
Description
The following code:
Resulted in this output:
This seems to happen because ReflectionProperty::isReadable() forwards the result of __isset() directly without validation, so a by-reference return can leak into a non-reference return slot.
PHP Version
Operating System
Ubuntu 24.04