Skip to content

Commit b20568d

Browse files
committed
Merge branch 'PHP-8.0' into PHP-8.1
* PHP-8.0: Fix memory leak
2 parents cab2f05 + 8258b77 commit b20568d

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Live range & free on return & TMP var of RETURN opcode
3+
--FILE--
4+
<?php
5+
class bar{
6+
public $y;
7+
function __destruct() {
8+
y;
9+
}
10+
}
11+
foreach(new bar as $y) {
12+
try {
13+
return new Exception;
14+
} catch(y) {
15+
}
16+
}
17+
?>
18+
--EXPECTF--
19+
Fatal error: Uncaught Error: Undefined constant "y" in %stemporary_cleaning_017.php:5
20+
Stack trace:
21+
#0 %stemporary_cleaning_017.php(10): bar->__destruct()
22+
#1 {main}
23+
thrown in %stemporary_cleaning_017.php on line 5

Zend/zend_vm_def.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7861,6 +7861,19 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
78617861
*/
78627862
const zend_live_range *range = find_live_range(
78637863
&EX(func)->op_array, throw_op_num, throw_op->op1.var);
7864+
/* free op1 of the corresponding RETURN */
7865+
for (i = throw_op_num; i < range->end; i++) {
7866+
if (EX(func)->op_array.opcodes[i].opcode == ZEND_FREE
7867+
|| EX(func)->op_array.opcodes[i].opcode == ZEND_FE_FREE) {
7868+
/* pass */
7869+
} else {
7870+
if (EX(func)->op_array.opcodes[i].opcode == ZEND_RETURN
7871+
&& (EX(func)->op_array.opcodes[i].op1_type & (IS_VAR|IS_TMP_VAR))) {
7872+
zval_ptr_dtor(EX_VAR(EX(func)->op_array.opcodes[i].op1.var));
7873+
}
7874+
break;
7875+
}
7876+
}
78647877
throw_op_num = range->end;
78657878
}
78667879

Zend/zend_vm_execute.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3085,6 +3085,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
30853085
*/
30863086
const zend_live_range *range = find_live_range(
30873087
&EX(func)->op_array, throw_op_num, throw_op->op1.var);
3088+
/* free op1 of the corresponding RETURN */
3089+
for (i = throw_op_num; i < range->end; i++) {
3090+
if (EX(func)->op_array.opcodes[i].opcode == ZEND_FREE
3091+
|| EX(func)->op_array.opcodes[i].opcode == ZEND_FE_FREE) {
3092+
/* pass */
3093+
} else {
3094+
if (EX(func)->op_array.opcodes[i].opcode == ZEND_RETURN
3095+
&& (EX(func)->op_array.opcodes[i].op1_type & (IS_VAR|IS_TMP_VAR))) {
3096+
zval_ptr_dtor(EX_VAR(EX(func)->op_array.opcodes[i].op1.var));
3097+
}
3098+
break;
3099+
}
3100+
}
30883101
throw_op_num = range->end;
30893102
}
30903103

0 commit comments

Comments
 (0)