Skip to content

Commit f0f774a

Browse files
committed
JIT x86: Fixed register clobbering in code produced for "$x[$y] %= $z".
1 parent cebff25 commit f0f774a

File tree

2 files changed

+57
-10
lines changed

2 files changed

+57
-10
lines changed

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4939,6 +4939,9 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
49394939

49404940
if (opcode == ZEND_MOD) {
49414941
result_reg = ZREG_RAX;
4942+
if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) {
4943+
| mov aword T1, r0 // save
4944+
}
49424945
} else if (Z_MODE(res_addr) == IS_REG) {
49434946
if ((opline->opcode == ZEND_SL || opline->opcode == ZEND_SR)
49444947
&& opline->op2_type != IS_CONST) {
@@ -5043,18 +5046,23 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
50435046
if (op2_lval == 0) {
50445047
| SET_EX_OPLINE opline, r0
50455048
| jmp ->mod_by_zero
5046-
} else if (op2_lval == -1) {
5047-
| xor Ra(result_reg), Ra(result_reg)
50485049
} else {
50495050
result_reg = ZREG_RDX;
5050-
| GET_ZVAL_LVAL ZREG_RAX, op1_addr
5051-
| GET_ZVAL_LVAL ZREG_RCX, op2_addr
5052-
|.if X64
5053-
| cqo
5054-
|.else
5055-
| cdq
5056-
|.endif
5057-
| idiv Ra(ZREG_RCX)
5051+
if (op2_lval == -1) {
5052+
| xor Ra(result_reg), Ra(result_reg)
5053+
} else {
5054+
| GET_ZVAL_LVAL ZREG_RAX, op1_addr
5055+
| GET_ZVAL_LVAL ZREG_RCX, op2_addr
5056+
|.if X64
5057+
| cqo
5058+
|.else
5059+
| cdq
5060+
|.endif
5061+
| idiv Ra(ZREG_RCX)
5062+
}
5063+
if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) {
5064+
| mov r0, aword T1 // restore
5065+
}
50585066
}
50595067
} else {
50605068
if (!op2_range || (op2_range->min <= 0 && op2_range->max >= 0)) {
@@ -5105,6 +5113,9 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
51055113
} else if (Z_MODE(op2_addr) == IS_REG) {
51065114
| idiv Ra(Z_REG(op2_addr))
51075115
}
5116+
if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) {
5117+
| mov r0, aword T1 // restore
5118+
}
51085119
}
51095120
} else if (same_ops) {
51105121
| GET_ZVAL_LVAL result_reg, op1_addr

ext/opcache/tests/jit/mod_003.phpt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
JIT MOD: 003
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+
opcache.jit=function
10+
--SKIPIF--
11+
<?php require_once('skipif.inc'); ?>
12+
--FILE--
13+
<?php
14+
class Test {
15+
public $prop = 0;
16+
}
17+
function test1($test) {
18+
$test[0] %= 3;
19+
return $test;
20+
}
21+
function test2($test) {
22+
$test->prop %= 3;
23+
return $test;
24+
}
25+
var_dump(test1([0]));
26+
var_dump(test2(new Test));
27+
?>
28+
--EXPECT--
29+
array(1) {
30+
[0]=>
31+
int(0)
32+
}
33+
object(Test)#1 (1) {
34+
["prop"]=>
35+
int(0)
36+
}

0 commit comments

Comments
 (0)