Skip to content

Commit 053c56f

Browse files
committed
Fixed bug #81226 (Integer overflow behavior is different with JIT enabled)
1 parent 0ba6dde commit 053c56f

File tree

3 files changed

+40
-22
lines changed

3 files changed

+40
-22
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ PHP NEWS
2222
. Fixed Bug #81255 (Memory leak in PHPUnit with functional JIT). (Dmitry)
2323
. Fixed Bug #80959 (infinite loop in building cfg during JIT compilation)
2424
(Nikita, Dmitry)
25+
. Fixed bug #81226 (Integer overflow behavior is different with JIT
26+
enabled). (Dmitry)
2527

2628
- Standard:
2729
. Fixed bug #72146 (Integer overflow on substr_replace). (cmb)

ext/opcache/jit/zend_jit.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,12 @@ static zend_bool zend_long_is_power_of_two(zend_long x)
193193
return (x > 0) && !(x & (x - 1));
194194
}
195195

196+
static zend_always_inline uint32_t zend_long_floor_log2(zend_long x)
197+
{
198+
ZEND_ASSERT(zend_long_is_power_of_two(x));
199+
return zend_ulong_ntz(x);
200+
}
201+
196202
#define OP_RANGE(ssa_op, opN) \
197203
(((opline->opN##_type & (IS_TMP_VAR|IS_VAR|IS_CV)) && \
198204
ssa->var_info && \

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4234,7 +4234,7 @@ static int zend_jit_math_long_long(dasm_State **Dst,
42344234
} else {
42354235
result_reg = Z_REG(res_addr);
42364236
}
4237-
} else if (Z_MODE(op1_addr) == IS_REG && Z_LAST_USE(op1_addr)) {
4237+
} else if (Z_MODE(op1_addr) == IS_REG && Z_LAST_USE(op1_addr) && !may_overflow) {
42384238
result_reg = Z_REG(op1_addr);
42394239
} else if (Z_REG(res_addr) != ZREG_R0) {
42404240
result_reg = ZREG_R0;
@@ -4245,32 +4245,42 @@ static int zend_jit_math_long_long(dasm_State **Dst,
42454245
}
42464246

42474247
if (opcode == ZEND_MUL &&
4248-
((Z_MODE(op2_addr) == IS_CONST_ZVAL &&
4249-
IS_SIGNED_32BIT(Z_LVAL_P(Z_ZV(op2_addr))) &&
4250-
is_power_of_two(Z_LVAL_P(Z_ZV(op2_addr)))) ||
4251-
(Z_MODE(op1_addr) == IS_CONST_ZVAL &&
4252-
IS_SIGNED_32BIT(Z_LVAL_P(Z_ZV(op1_addr))) &&
4253-
is_power_of_two(Z_LVAL_P(Z_ZV(op1_addr)))))) {
4254-
if (Z_MODE(op2_addr) == IS_CONST_ZVAL) {
4255-
if (Z_MODE(op1_addr) == IS_REG && Z_LVAL_P(Z_ZV(op2_addr)) == 2) {
4256-
| lea Ra(result_reg), [Ra(Z_REG(op1_addr))+Ra(Z_REG(op1_addr))]
4257-
} else {
4258-
| GET_ZVAL_LVAL result_reg, op1_addr
4259-
| shl Ra(result_reg), floor_log2(Z_LVAL_P(Z_ZV(op2_addr)))
4260-
}
4248+
Z_MODE(op2_addr) == IS_CONST_ZVAL &&
4249+
Z_LVAL_P(Z_ZV(op2_addr)) == 2) {
4250+
if (Z_MODE(op1_addr) == IS_REG && !may_overflow) {
4251+
| lea Ra(result_reg), [Ra(Z_REG(op1_addr))+Ra(Z_REG(op1_addr))]
42614252
} else {
4262-
if (Z_MODE(op2_addr) == IS_REG && Z_LVAL_P(Z_ZV(op1_addr)) == 2) {
4263-
| lea Ra(result_reg), [Ra(Z_REG(op2_addr))+Ra(Z_REG(op2_addr))]
4264-
} else {
4265-
| GET_ZVAL_LVAL result_reg, op2_addr
4266-
| shl Ra(result_reg), floor_log2(Z_LVAL_P(Z_ZV(op1_addr)))
4267-
}
4253+
| GET_ZVAL_LVAL result_reg, op1_addr
4254+
| add Ra(result_reg), Ra(result_reg)
42684255
}
4256+
} else if (opcode == ZEND_MUL &&
4257+
Z_MODE(op2_addr) == IS_CONST_ZVAL &&
4258+
!may_overflow &&
4259+
Z_LVAL_P(Z_ZV(op2_addr)) > 0 &&
4260+
zend_long_is_power_of_two(Z_LVAL_P(Z_ZV(op2_addr)))) {
4261+
| GET_ZVAL_LVAL result_reg, op1_addr
4262+
| shl Ra(result_reg), zend_long_floor_log2(Z_LVAL_P(Z_ZV(op2_addr)))
4263+
} else if (opcode == ZEND_MUL &&
4264+
Z_MODE(op1_addr) == IS_CONST_ZVAL &&
4265+
Z_LVAL_P(Z_ZV(op1_addr)) == 2) {
4266+
if (Z_MODE(op2_addr) == IS_REG && !may_overflow) {
4267+
| lea Ra(result_reg), [Ra(Z_REG(op2_addr))+Ra(Z_REG(op2_addr))]
4268+
} else {
4269+
| GET_ZVAL_LVAL result_reg, op2_addr
4270+
| add Ra(result_reg), Ra(result_reg)
4271+
}
4272+
} else if (opcode == ZEND_MUL &&
4273+
Z_MODE(op1_addr) == IS_CONST_ZVAL &&
4274+
!may_overflow &&
4275+
Z_LVAL_P(Z_ZV(op1_addr)) > 0 &&
4276+
zend_long_is_power_of_two(Z_LVAL_P(Z_ZV(op1_addr)))) {
4277+
| GET_ZVAL_LVAL result_reg, op2_addr
4278+
| shl Ra(result_reg), zend_long_floor_log2(Z_LVAL_P(Z_ZV(op1_addr)))
42694279
} else if (opcode == ZEND_DIV &&
42704280
(Z_MODE(op2_addr) == IS_CONST_ZVAL &&
4271-
is_power_of_two(Z_LVAL_P(Z_ZV(op2_addr))))) {
4281+
zend_long_is_power_of_two(Z_LVAL_P(Z_ZV(op2_addr))))) {
42724282
| GET_ZVAL_LVAL result_reg, op1_addr
4273-
| shr Ra(result_reg), floor_log2(Z_LVAL_P(Z_ZV(op2_addr)))
4283+
| shr Ra(result_reg), zend_long_floor_log2(Z_LVAL_P(Z_ZV(op2_addr)))
42744284
} else if (opcode == ZEND_ADD &&
42754285
!may_overflow &&
42764286
Z_MODE(op1_addr) == IS_REG &&

0 commit comments

Comments
 (0)