mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Merge remote-tracking branch 'derickr/gh10072-execute-ex' into PHP-8.1
This commit is contained in:
commit
29926c3262
4
NEWS
4
NEWS
@ -5,6 +5,10 @@ PHP NEWS
|
||||
- Apache:
|
||||
. Fixed bug GH-9949 (Partial content on incomplete POST request). (cmb)
|
||||
|
||||
- Core:
|
||||
. Fixed bug GH-10072 (PHP crashes when execute_ex is overridden and a __call
|
||||
trampoline is used from internal code). (Derick)
|
||||
|
||||
- Date:
|
||||
. Fixed bug GH-9891 (DateTime modify with unixtimestamp (@) must work like
|
||||
setTimestamp). (Derick)
|
||||
|
20
Zend/tests/gh10072-2.phpt
Normal file
20
Zend/tests/gh10072-2.phpt
Normal file
@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
GH-10072 (PHP crashes when execute_ex is overridden and a trampoline is used from internal code during shutdown)
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--INI--
|
||||
zend_test.replace_zend_execute_ex=1
|
||||
opcache.jit=disable
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class TrampolineTest {
|
||||
public function __call(string $name, array $arguments) {
|
||||
echo 'Trampoline for ', $name, PHP_EOL;
|
||||
}
|
||||
}
|
||||
|
||||
register_shutdown_function([new TrampolineTest(), 'shutdown']);
|
||||
?>
|
||||
--EXPECT--
|
||||
Trampoline for shutdown
|
106
Zend/tests/gh10072.phpt
Normal file
106
Zend/tests/gh10072.phpt
Normal file
@ -0,0 +1,106 @@
|
||||
--TEST--
|
||||
GH-10072 (PHP crashes when execute_ex is overridden and a trampoline is used from internal code)
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--INI--
|
||||
zend_test.replace_zend_execute_ex=1
|
||||
opcache.jit=disable
|
||||
--FILE--
|
||||
<?php
|
||||
class DummyStreamWrapper
|
||||
{
|
||||
/** @var resource|null */
|
||||
public $context;
|
||||
|
||||
/** @var resource|null */
|
||||
public $handle;
|
||||
|
||||
|
||||
public function stream_cast(int $castAs)
|
||||
{
|
||||
return $this->handle;
|
||||
}
|
||||
|
||||
|
||||
public function stream_close(): void
|
||||
{
|
||||
}
|
||||
|
||||
public function stream_open(string $path, string $mode, int $options = 0, ?string &$openedPath = null): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function stream_read(int $count)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public function stream_seek(int $offset, int $whence = SEEK_SET): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function stream_set_option(int $option, int $arg1, ?int $arg2): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public function stream_stat()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
public function stream_tell()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
public function stream_truncate(int $newSize): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function stream_write(string $data)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public function unlink(string $path): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class TrampolineTest {
|
||||
/** @var resource|null */
|
||||
public $context;
|
||||
|
||||
/** @var object|null */
|
||||
private $wrapper;
|
||||
|
||||
public function __call(string $name, array $arguments) {
|
||||
if (!$this->wrapper) {
|
||||
$this->wrapper = new DummyStreamWrapper();
|
||||
}
|
||||
echo 'Trampoline for ', $name, PHP_EOL;
|
||||
return $this->wrapper->$name(...$arguments);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stream_wrapper_register('custom', TrampolineTest::class);
|
||||
|
||||
|
||||
$fp = fopen("custom://myvar", "r+");
|
||||
?>
|
||||
--EXPECT--
|
||||
Trampoline for stream_open
|
||||
Trampoline for stream_close
|
@ -8663,7 +8663,9 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER))
|
||||
SAVE_OPLINE_EX();
|
||||
ZEND_OBSERVER_FCALL_BEGIN(execute_data);
|
||||
execute_data = EX(prev_execute_data);
|
||||
LOAD_OPLINE();
|
||||
if (execute_data) {
|
||||
LOAD_OPLINE();
|
||||
}
|
||||
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
||||
zend_execute_ex(call);
|
||||
}
|
||||
@ -8713,7 +8715,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER))
|
||||
|
||||
execute_data = EG(current_execute_data);
|
||||
|
||||
if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) {
|
||||
if (!execute_data || !EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) {
|
||||
ZEND_VM_RETURN();
|
||||
}
|
||||
|
||||
|
@ -3319,7 +3319,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
|
||||
SAVE_OPLINE_EX();
|
||||
|
||||
execute_data = EX(prev_execute_data);
|
||||
LOAD_OPLINE();
|
||||
if (execute_data) {
|
||||
LOAD_OPLINE();
|
||||
}
|
||||
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
||||
zend_execute_ex(call);
|
||||
}
|
||||
@ -3369,7 +3371,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z
|
||||
|
||||
execute_data = EG(current_execute_data);
|
||||
|
||||
if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) {
|
||||
if (!execute_data || !EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) {
|
||||
ZEND_VM_RETURN();
|
||||
}
|
||||
|
||||
@ -3456,7 +3458,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_
|
||||
SAVE_OPLINE_EX();
|
||||
zend_observer_fcall_begin(execute_data);
|
||||
execute_data = EX(prev_execute_data);
|
||||
LOAD_OPLINE();
|
||||
if (execute_data) {
|
||||
LOAD_OPLINE();
|
||||
}
|
||||
ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP);
|
||||
zend_execute_ex(call);
|
||||
}
|
||||
@ -3506,7 +3510,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_
|
||||
|
||||
execute_data = EG(current_execute_data);
|
||||
|
||||
if (!EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) {
|
||||
if (!execute_data || !EX(func) || !ZEND_USER_CODE(EX(func)->type) || (call_info & ZEND_CALL_TOP)) {
|
||||
ZEND_VM_RETURN();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user