Skip to content

Commit 24b1c24

Browse files
committed
JIT: Fix missing free on JMPZ_EX with op1 == res
We need to free the operand before we overwrite it with the result.
1 parent 65fa6da commit 24b1c24

File tree

2 files changed

+50
-25
lines changed

2 files changed

+50
-25
lines changed

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 18 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6661,6 +6661,24 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, int b,
66616661
| SAVE_VALID_OPLINE opline
66626662
| EXT_CALL zend_is_true, r0
66636663

6664+
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) &&
6665+
(op1_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
6666+
op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op1.var);
6667+
6668+
| IF_NOT_ZVAL_REFCOUNTED op1_addr, >3
6669+
| GET_ZVAL_PTR FCARG1a, op1_addr
6670+
| GC_DELREF FCARG1a
6671+
| jnz >3
6672+
| mov aword T1, r0 // save
6673+
| ZVAL_DTOR_FUNC op1_info, opline
6674+
| mov r0, aword T1 // restore
6675+
|3:
6676+
}
6677+
if (zend_may_throw(opline, op_array, ssa)) {
6678+
| MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r1
6679+
| jne ->exception_handler_undef
6680+
}
6681+
66646682
if (set_bool) {
66656683
if (set_bool_not) {
66666684
| neg eax
@@ -6669,12 +6687,6 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, int b,
66696687
| add eax, 2
66706688
}
66716689
| SET_ZVAL_TYPE_INFO res_addr, eax
6672-
| FREE_OP opline->op1_type, opline->op1, op1_info, !(op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE|MAY_BE_LONG)), op_array, opline
6673-
if (zend_may_throw(opline, op_array, ssa)) {
6674-
if (!zend_jit_check_exception_undef_result(Dst, opline)) {
6675-
return 0;
6676-
}
6677-
}
66786690
if (true_label != (uint32_t)-1 || false_label != (uint32_t)-1) {
66796691
| CMP_ZVAL_TYPE res_addr, IS_FALSE
66806692
if (true_label != (uint32_t)-1) {
@@ -6693,25 +6705,6 @@ static int zend_jit_bool_jmpznz(dasm_State **Dst, const zend_op *opline, int b,
66936705
|.code
66946706
}
66956707
} else {
6696-
6697-
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) &&
6698-
(op1_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
6699-
op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op1.var);
6700-
6701-
| IF_NOT_ZVAL_REFCOUNTED op1_addr, >3
6702-
| GET_ZVAL_PTR FCARG1a, op1_addr
6703-
| GC_DELREF FCARG1a
6704-
| jnz >3
6705-
| mov aword T1, r0 // save
6706-
| ZVAL_DTOR_FUNC op1_info, opline
6707-
| mov r0, aword T1 // restore
6708-
|3:
6709-
}
6710-
if (zend_may_throw(opline, op_array, ssa)) {
6711-
| MEM_OP2_1_ZTS cmp, aword, executor_globals, exception, 0, r1
6712-
| jne ->exception_handler_undef
6713-
}
6714-
67156708
| test r0, r0
67166709
if (true_label != (uint32_t)-1) {
67176710
| jne =>true_label
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
JIT JMPZ_EX: Operand needs to be freed even if same as result
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.file_update_protection=0
7+
opcache.jit_buffer_size=1M
8+
opcache.protect_memory=1
9+
--SKIPIF--
10+
<?php require_once('skipif.inc'); ?>
11+
--FILE--
12+
<?php
13+
class Test {
14+
public $prop;
15+
public function method() {
16+
return $this->prop && $this->prop->method2();
17+
}
18+
}
19+
20+
class Test2 {
21+
public function method2() {
22+
return true;
23+
}
24+
};
25+
26+
$test = new Test;
27+
$test->prop = new Test2;
28+
var_dump($test->method());
29+
30+
?>
31+
--EXPECT--
32+
bool(true)

0 commit comments

Comments
 (0)