Skip to content

Commit 8258b77

Browse files
committed
Fix memory leak
Fixes oss-fuzz #51622
1 parent e488f7b commit 8258b77

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed
+23
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

+13
Original file line numberDiff line numberDiff line change
@@ -7791,6 +7791,19 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
77917791
*/
77927792
const zend_live_range *range = find_live_range(
77937793
&EX(func)->op_array, throw_op_num, throw_op->op1.var);
7794+
/* free op1 of the corresponding RETURN */
7795+
for (i = throw_op_num; i < range->end; i++) {
7796+
if (EX(func)->op_array.opcodes[i].opcode == ZEND_FREE
7797+
|| EX(func)->op_array.opcodes[i].opcode == ZEND_FE_FREE) {
7798+
/* pass */
7799+
} else {
7800+
if (EX(func)->op_array.opcodes[i].opcode == ZEND_RETURN
7801+
&& (EX(func)->op_array.opcodes[i].op1_type & (IS_VAR|IS_TMP_VAR))) {
7802+
zval_ptr_dtor(EX_VAR(EX(func)->op_array.opcodes[i].op1.var));
7803+
}
7804+
break;
7805+
}
7806+
}
77947807
throw_op_num = range->end;
77957808
}
77967809

Zend/zend_vm_execute.h

+13
Original file line numberDiff line numberDiff line change
@@ -2943,6 +2943,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
29432943
*/
29442944
const zend_live_range *range = find_live_range(
29452945
&EX(func)->op_array, throw_op_num, throw_op->op1.var);
2946+
/* free op1 of the corresponding RETURN */
2947+
for (i = throw_op_num; i < range->end; i++) {
2948+
if (EX(func)->op_array.opcodes[i].opcode == ZEND_FREE
2949+
|| EX(func)->op_array.opcodes[i].opcode == ZEND_FE_FREE) {
2950+
/* pass */
2951+
} else {
2952+
if (EX(func)->op_array.opcodes[i].opcode == ZEND_RETURN
2953+
&& (EX(func)->op_array.opcodes[i].op1_type & (IS_VAR|IS_TMP_VAR))) {
2954+
zval_ptr_dtor(EX_VAR(EX(func)->op_array.opcodes[i].op1.var));
2955+
}
2956+
break;
2957+
}
2958+
}
29462959
throw_op_num = range->end;
29472960
}
29482961

0 commit comments

Comments
 (0)