Skip to content

Commit 81007bd

Browse files
committed
Merge branch 'PHP-8.1'
* PHP-8.1: JIT: Fixed use-after-free caused by shift by negative number
2 parents 1f18379 + 971354c commit 81007bd

File tree

3 files changed

+82
-0
lines changed

3 files changed

+82
-0
lines changed

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3594,6 +3594,15 @@ static int zend_jit_load_var(dasm_State **Dst, uint32_t info, int var, zend_reg
35943594
return zend_jit_load_reg(Dst, src, dst, info);
35953595
}
35963596

3597+
static int zend_jit_invalidate_var_if_necessary(dasm_State **Dst, zend_uchar op_type, zend_jit_addr addr, znode_op op)
3598+
{
3599+
if ((op_type & (IS_TMP_VAR|IS_VAR)) && Z_MODE(addr) == IS_REG && !Z_LOAD(addr) && !Z_STORE(addr)) {
3600+
zend_jit_addr dst = ZEND_ADDR_MEM_ZVAL(ZREG_FP, op.var);
3601+
| SET_ZVAL_TYPE_INFO dst, IS_UNDEF, TMP1w, TMP2
3602+
}
3603+
return 1;
3604+
}
3605+
35973606
static int zend_jit_update_regs(dasm_State **Dst, uint32_t var, zend_jit_addr src, zend_jit_addr dst, uint32_t info)
35983607
{
35993608
if (!zend_jit_same_addr(src, dst)) {
@@ -4654,6 +4663,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
46544663
if (EXPECTED(op2_lval > 0)) {
46554664
| mov Rx(result_reg), xzr
46564665
} else {
4666+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
4667+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
46574668
| SET_EX_OPLINE opline, REG0
46584669
| b ->negative_shift
46594670
}
@@ -4683,6 +4694,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
46834694
| mov Rx(result_reg), xzr
46844695
| cmp Rx(op2_reg), xzr
46854696
| bgt >1
4697+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
4698+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
46864699
| SET_EX_OPLINE opline, REG0
46874700
| b ->negative_shift
46884701
|.code
@@ -4700,6 +4713,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
47004713
if (EXPECTED(op2_lval > 0)) {
47014714
| asr Rx(result_reg), Rx(result_reg), #((SIZEOF_ZEND_LONG * 8) - 1)
47024715
} else {
4716+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
4717+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
47034718
| SET_EX_OPLINE opline, REG0
47044719
| b ->negative_shift
47054720
}
@@ -4725,6 +4740,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
47254740
| cmp Rx(op2_reg), xzr
47264741
| mov Rx(op2_reg), #((SIZEOF_ZEND_LONG * 8) - 1)
47274742
| bgt >1
4743+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
4744+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
47284745
| SET_EX_OPLINE opline, REG0
47294746
| b ->negative_shift
47304747
|.code
@@ -4737,6 +4754,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
47374754
zend_long op2_lval = Z_LVAL_P(Z_ZV(op2_addr));
47384755

47394756
if (op2_lval == 0) {
4757+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
4758+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
47404759
| SET_EX_OPLINE opline, REG0
47414760
| b ->mod_by_zero
47424761
} else if (op2_lval == -1) {
@@ -4771,6 +4790,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
47714790
| cbz Rx(op2_reg), >1
47724791
|.cold_code
47734792
|1:
4793+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
4794+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
47744795
| SET_EX_OPLINE opline, REG0
47754796
| b ->mod_by_zero
47764797
|.code

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3939,6 +3939,15 @@ static int zend_jit_load_var(dasm_State **Dst, uint32_t info, int var, zend_reg
39393939
return zend_jit_load_reg(Dst, src, dst, info);
39403940
}
39413941

3942+
static int zend_jit_invalidate_var_if_necessary(dasm_State **Dst, zend_uchar op_type, zend_jit_addr addr, znode_op op)
3943+
{
3944+
if ((op_type & (IS_TMP_VAR|IS_VAR)) && Z_MODE(addr) == IS_REG && !Z_LOAD(addr) && !Z_STORE(addr)) {
3945+
zend_jit_addr dst = ZEND_ADDR_MEM_ZVAL(ZREG_FP, op.var);
3946+
| SET_ZVAL_TYPE_INFO dst, IS_UNDEF
3947+
}
3948+
return 1;
3949+
}
3950+
39423951
static int zend_jit_update_regs(dasm_State **Dst, uint32_t var, zend_jit_addr src, zend_jit_addr dst, uint32_t info)
39433952
{
39443953
if (!zend_jit_same_addr(src, dst)) {
@@ -5081,6 +5090,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
50815090
if (EXPECTED(op2_lval > 0)) {
50825091
| xor Ra(result_reg), Ra(result_reg)
50835092
} else {
5093+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
5094+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
50845095
| SET_EX_OPLINE opline, r0
50855096
| jmp ->negative_shift
50865097
}
@@ -5104,6 +5115,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
51045115
| cmp r1, 0
51055116
| mov Ra(result_reg), 0
51065117
| jg >1
5118+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
5119+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
51075120
| SET_EX_OPLINE opline, r0
51085121
| jmp ->negative_shift
51095122
|.code
@@ -5121,6 +5134,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
51215134
if (EXPECTED(op2_lval > 0)) {
51225135
| sar Ra(result_reg), (SIZEOF_ZEND_LONG * 8) - 1
51235136
} else {
5137+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
5138+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
51245139
| SET_EX_OPLINE opline, r0
51255140
| jmp ->negative_shift
51265141
}
@@ -5141,6 +5156,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
51415156
| cmp r1, 0
51425157
| mov r1, (SIZEOF_ZEND_LONG * 8) - 1
51435158
| jg >1
5159+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
5160+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
51445161
| SET_EX_OPLINE opline, r0
51455162
| jmp ->negative_shift
51465163
|.code
@@ -5153,6 +5170,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
51535170
zend_long op2_lval = Z_LVAL_P(Z_ZV(op2_addr));
51545171

51555172
if (op2_lval == 0) {
5173+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
5174+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
51565175
| SET_EX_OPLINE opline, r0
51575176
| jmp ->mod_by_zero
51585177
} else if (zend_long_is_power_of_two(op2_lval) && op1_range && op1_range->min >= 0) {
@@ -5192,6 +5211,8 @@ static int zend_jit_long_math_helper(dasm_State **Dst,
51925211
| jz >1
51935212
|.cold_code
51945213
|1:
5214+
zend_jit_invalidate_var_if_necessary(Dst, op1_type, op1_addr, op1);
5215+
zend_jit_invalidate_var_if_necessary(Dst, op2_type, op2_addr, op2);
51955216
| SET_EX_OPLINE opline, r0
51965217
| jmp ->mod_by_zero
51975218
|.code
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
JIT Shift Right: 004
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+
--FILE--
10+
<?php
11+
function test() {
12+
$j = 2;
13+
for ($i = 0; $i < 10;
14+
$i + $b = $a + $a = $a + $a = $a +
15+
$a = !$a +
16+
$c[0] .= 0xfff0001/34028236692903846346336*6) {
17+
$a =!$a + $a &= 74444444 - 444 >> 4 - $j++;
18+
if ($j > 14) break;
19+
}
20+
}
21+
test();
22+
?>
23+
--EXPECTF--
24+
Warning: Undefined variable $a in %sshift_right_004.php on line 8
25+
26+
Warning: Undefined variable $a in %sshift_right_004.php on line 8
27+
28+
Warning: Undefined variable $c in %sshift_right_004.php on line 7
29+
30+
Warning: Undefined array key 0 in %sshift_right_004.php on line 7
31+
32+
Warning: A non-numeric value encountered in %sshift_right_004.php on line 7
33+
34+
Warning: A non-numeric value encountered in %sshift_right_004.php on line 7
35+
36+
Fatal error: Uncaught ArithmeticError: Bit shift by negative number in %sshift_right_004.php:8
37+
Stack trace:
38+
#0 %sshift_right_004.php(12): test()
39+
#1 {main}
40+
thrown in %sshift_right_004.php on line 8

0 commit comments

Comments
 (0)