Skip to content

Commit 271cbe5

Browse files
committed
Merge branch 'PHP-8.0' into PHP-8.1
* PHP-8.0: Partially fix handling of exceptions thrown in interrupt handlers
2 parents 1039852 + fa0b84a commit 271cbe5

File tree

5 files changed

+103
-0
lines changed

5 files changed

+103
-0
lines changed

Zend/zend_vm_def.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9793,6 +9793,20 @@ ZEND_VM_HELPER(zend_interrupt_helper, ANY, ANY)
97939793
zend_timeout();
97949794
} else if (zend_interrupt_function) {
97959795
zend_interrupt_function(execute_data);
9796+
if (EG(exception)) {
9797+
/* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */
9798+
const zend_op *throw_op = EG(opline_before_exception);
9799+
9800+
if (throw_op
9801+
&& throw_op->result_type & (IS_TMP_VAR|IS_VAR)
9802+
&& throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT
9803+
&& throw_op->opcode != ZEND_ADD_ARRAY_UNPACK
9804+
&& throw_op->opcode != ZEND_ROPE_INIT
9805+
&& throw_op->opcode != ZEND_ROPE_ADD) {
9806+
ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var));
9807+
9808+
}
9809+
}
97969810
ZEND_VM_ENTER();
97979811
}
97989812
ZEND_VM_CONTINUE();

Zend/zend_vm_execute.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3528,6 +3528,20 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_interrupt_he
35283528
zend_timeout();
35293529
} else if (zend_interrupt_function) {
35303530
zend_interrupt_function(execute_data);
3531+
if (EG(exception)) {
3532+
/* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */
3533+
const zend_op *throw_op = EG(opline_before_exception);
3534+
3535+
if (throw_op
3536+
&& throw_op->result_type & (IS_TMP_VAR|IS_VAR)
3537+
&& throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT
3538+
&& throw_op->opcode != ZEND_ADD_ARRAY_UNPACK
3539+
&& throw_op->opcode != ZEND_ROPE_INIT
3540+
&& throw_op->opcode != ZEND_ROPE_ADD) {
3541+
ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var));
3542+
3543+
}
3544+
}
35313545
ZEND_VM_ENTER();
35323546
}
35333547
ZEND_VM_CONTINUE();

ext/pcntl/tests/bug81577.phpt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Bug #81577: (Exceptions in interrupt handlers)
3+
--EXTENSIONS--
4+
pcntl
5+
posix
6+
--FILE--
7+
<?php
8+
class C {
9+
public static $cond = 1;
10+
public static $a;
11+
}
12+
13+
C::$a = [ C::$cond ]; // make countable zval
14+
15+
pcntl_async_signals(true);
16+
pcntl_signal(SIGTERM, function ($signo) { throw new Exception("Signal"); });
17+
for ($i = 0; $i < 5; $i++) {
18+
try {
19+
C::$a + C::$a;
20+
posix_kill(posix_getpid(), SIGTERM) + C::$cond;
21+
} catch (Throwable $ex) {
22+
echo get_class($ex) , " : " , $ex->getMessage() , "\n";
23+
}
24+
}
25+
?>
26+
--EXPECT--
27+
Exception : Signal
28+
Exception : Signal
29+
Exception : Signal
30+
Exception : Signal
31+
Exception : Signal

ext/pcntl/tests/bug81577_2.phpt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
--TEST--
2+
Bug #81577: (Exceptions in interrupt handlers: ADD_ARRAY_ELEMENT)
3+
--EXTENSIONS--
4+
pcntl
5+
posix
6+
--FILE--
7+
<?php
8+
pcntl_async_signals(true);
9+
pcntl_signal(SIGTERM, function ($signo) {});
10+
try {
11+
$a = [1, posix_kill(posix_getpid(), SIGTERM), 2];
12+
} catch (Throwable $ex) {
13+
echo get_class($ex) , " : " , $ex->getMessage() , "\n";
14+
}
15+
var_dump($a);
16+
?>
17+
--EXPECT--
18+
array(3) {
19+
[0]=>
20+
int(1)
21+
[1]=>
22+
bool(true)
23+
[2]=>
24+
int(2)
25+
}

ext/pcntl/tests/bug81577_3.phpt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Bug #81577: (Exceptions in interrupt handlers: cleanup_live_vars)
3+
--EXTENSIONS--
4+
pcntl
5+
posix
6+
--XFAIL--
7+
leaks are not fixed yet
8+
--FILE--
9+
<?php
10+
pcntl_async_signals(true);
11+
pcntl_signal(SIGTERM, function ($signo) { throw new Exception("Signal"); });
12+
try {
13+
array_merge([1], [2]) + posix_kill(posix_getpid(), SIGTERM);
14+
} catch (Throwable $ex) {
15+
echo get_class($ex) , " : " , $ex->getMessage() , "\n";
16+
}
17+
?>
18+
--EXPECT--
19+
Exception : Signal

0 commit comments

Comments
 (0)