Merge branch 'PHP-8.0' into PHP-8.1

* PHP-8.0:
  Partially fix handling of exceptions thrown in interrupt handlers
This commit is contained in:
Dmitry Stogov 2021-11-11 21:01:40 +03:00
commit 271cbe527c
5 changed files with 103 additions and 0 deletions

View File

@ -9793,6 +9793,20 @@ ZEND_VM_HELPER(zend_interrupt_helper, ANY, ANY)
zend_timeout();
} else if (zend_interrupt_function) {
zend_interrupt_function(execute_data);
if (EG(exception)) {
/* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */
const zend_op *throw_op = EG(opline_before_exception);
if (throw_op
&& throw_op->result_type & (IS_TMP_VAR|IS_VAR)
&& throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT
&& throw_op->opcode != ZEND_ADD_ARRAY_UNPACK
&& throw_op->opcode != ZEND_ROPE_INIT
&& throw_op->opcode != ZEND_ROPE_ADD) {
ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var));
}
}
ZEND_VM_ENTER();
}
ZEND_VM_CONTINUE();

View File

@ -3528,6 +3528,20 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_he
zend_timeout();
} else if (zend_interrupt_function) {
zend_interrupt_function(execute_data);
if (EG(exception)) {
/* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */
const zend_op *throw_op = EG(opline_before_exception);
if (throw_op
&& throw_op->result_type & (IS_TMP_VAR|IS_VAR)
&& throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT
&& throw_op->opcode != ZEND_ADD_ARRAY_UNPACK
&& throw_op->opcode != ZEND_ROPE_INIT
&& throw_op->opcode != ZEND_ROPE_ADD) {
ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var));
}
}
ZEND_VM_ENTER();
}
ZEND_VM_CONTINUE();

View File

@ -0,0 +1,31 @@
--TEST--
Bug #81577: (Exceptions in interrupt handlers)
--EXTENSIONS--
pcntl
posix
--FILE--
<?php
class C {
public static $cond = 1;
public static $a;
}
C::$a = [ C::$cond ]; // make countable zval
pcntl_async_signals(true);
pcntl_signal(SIGTERM, function ($signo) { throw new Exception("Signal"); });
for ($i = 0; $i < 5; $i++) {
try {
C::$a + C::$a;
posix_kill(posix_getpid(), SIGTERM) + C::$cond;
} catch (Throwable $ex) {
echo get_class($ex) , " : " , $ex->getMessage() , "\n";
}
}
?>
--EXPECT--
Exception : Signal
Exception : Signal
Exception : Signal
Exception : Signal
Exception : Signal

View File

@ -0,0 +1,25 @@
--TEST--
Bug #81577: (Exceptions in interrupt handlers: ADD_ARRAY_ELEMENT)
--EXTENSIONS--
pcntl
posix
--FILE--
<?php
pcntl_async_signals(true);
pcntl_signal(SIGTERM, function ($signo) {});
try {
$a = [1, posix_kill(posix_getpid(), SIGTERM), 2];
} catch (Throwable $ex) {
echo get_class($ex) , " : " , $ex->getMessage() , "\n";
}
var_dump($a);
?>
--EXPECT--
array(3) {
[0]=>
int(1)
[1]=>
bool(true)
[2]=>
int(2)
}

View File

@ -0,0 +1,19 @@
--TEST--
Bug #81577: (Exceptions in interrupt handlers: cleanup_live_vars)
--EXTENSIONS--
pcntl
posix
--XFAIL--
leaks are not fixed yet
--FILE--
<?php
pcntl_async_signals(true);
pcntl_signal(SIGTERM, function ($signo) { throw new Exception("Signal"); });
try {
array_merge([1], [2]) + posix_kill(posix_getpid(), SIGTERM);
} catch (Throwable $ex) {
echo get_class($ex) , " : " , $ex->getMessage() , "\n";
}
?>
--EXPECT--
Exception : Signal