From 261a08af65168e24c43a81321284f3f461f3500d Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 24 Oct 2022 12:02:28 +0300 Subject: [PATCH] JIT: Fix incorrect EX(opline) override Fixes oss-fuzz #52674 --- ext/opcache/jit/zend_jit_arm64.dasc | 23 +++++++++++--------- ext/opcache/jit/zend_jit_x86.dasc | 23 +++++++++++--------- ext/opcache/tests/jit/fetch_dim_rw_004.phpt | 24 +++++++++++++++++++++ 3 files changed, 50 insertions(+), 20 deletions(-) create mode 100644 ext/opcache/tests/jit/fetch_dim_rw_004.phpt diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index f7bd6723927..e436ffcaa82 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -5342,7 +5342,6 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o | // hval = Z_LVAL_P(dim); | GET_ZVAL_LVAL ZREG_FCARG2, op2_addr, TMP1 } - | SET_EX_OPLINE opline, REG0 if (packed_loaded) { | EXT_CALL zend_jit_hash_index_lookup_rw_no_packed, REG0 } else { @@ -5465,7 +5464,6 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o } break; case BP_VAR_RW: - | SET_EX_OPLINE opline, REG0 if (opline->op2_type != IS_CONST) { | EXT_CALL zend_jit_symtable_lookup_rw, REG0 } else { @@ -5512,7 +5510,9 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o |.cold_code |3: } - | SET_EX_OPLINE opline, REG0 + if (type != BP_VAR_RW) { + | SET_EX_OPLINE opline, REG0 + } | LOAD_ZVAL_ADDR FCARG2x, op2_addr switch (type) { case BP_VAR_R: @@ -6233,6 +6233,7 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 op2_addr = (opline->op2_type != IS_UNUSED) ? OP2_ADDR() : 0; op3_addr = OP1_DATA_ADDR(); + | SET_EX_OPLINE opline, REG0 if (op1_info & MAY_BE_REF) { | LOAD_ZVAL_ADDR FCARG1x, op1_addr | IF_NOT_Z_TYPE FCARG1x, IS_REFERENCE, >1, TMP1w @@ -6244,7 +6245,6 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 | b >3 |.cold_code |2: - | SET_EX_OPLINE opline, REG0 | EXT_CALL zend_jit_prepare_assign_dim_ref, REG0 | mov FCARG1x, RETVALx | cbnz RETVALx, >1 @@ -6277,7 +6277,6 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 if (op1_info & MAY_BE_NULL) { | IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1, ZREG_TMP1 } - | SET_EX_OPLINE opline, REG0 | LOAD_32BIT_VAL FCARG1x, opline->op1.var | EXT_CALL zend_jit_undefined_op_helper, REG0 |1: @@ -6359,7 +6358,6 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 |2: | LOAD_ZVAL_ADDR FCARG2x, op3_addr | LOAD_ADDR CARG3, binary_op - | SET_EX_OPLINE opline, REG0 if (((opline+1)->op1_type & (IS_TMP_VAR|IS_VAR)) && (op1_data_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) { | EXT_CALL zend_jit_assign_op_to_typed_ref_tmp, REG0 @@ -6417,7 +6415,6 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 |7: } - | SET_EX_OPLINE opline, REG0 if (Z_REG(op1_addr) != ZREG_FCARG1 || Z_OFFSET(op1_addr) != 0) { | LOAD_ZVAL_ADDR FCARG1x, op1_addr } @@ -11532,6 +11529,9 @@ static int zend_jit_fetch_dim(dasm_State **Dst, op2_addr = (opline->op2_type != IS_UNUSED) ? OP2_ADDR() : 0; + if (opline->opcode == ZEND_FETCH_DIM_RW) { + | SET_EX_OPLINE opline, REG0 + } if (op1_info & MAY_BE_REF) { may_throw = 1; | LOAD_ZVAL_ADDR FCARG1x, op1_addr @@ -11545,7 +11545,9 @@ static int zend_jit_fetch_dim(dasm_State **Dst, |.cold_code |2: | SET_EX_OPLINE opline, REG0 - | EXT_CALL zend_jit_prepare_assign_dim_ref, REG0 + if (if (opline->opcode != ZEND_FETCH_DIM_RW) { + | EXT_CALL zend_jit_prepare_assign_dim_ref, REG0 + } | mov FCARG1x, RETVALx | cbnz FCARG1x, >1 | b ->exception_handler_undef @@ -11579,7 +11581,6 @@ static int zend_jit_fetch_dim(dasm_State **Dst, if (op1_info & MAY_BE_NULL) { | IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1, ZREG_TMP1 } - | SET_EX_OPLINE opline, REG0 | LOAD_32BIT_VAL FCARG1w, opline->op1.var | EXT_CALL zend_jit_undefined_op_helper, REG0 |1: @@ -11666,7 +11667,9 @@ static int zend_jit_fetch_dim(dasm_State **Dst, |7: } - | SET_EX_OPLINE opline, REG0 + if (opline->opcode != ZEND_FETCH_DIM_RW) { + | SET_EX_OPLINE opline, REG0 + } if (Z_REG(op1_addr) != ZREG_FCARG1 || Z_OFFSET(op1_addr) != 0) { | LOAD_ZVAL_ADDR FCARG1x, op1_addr } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index ad80a3b6290..d0f33eafa67 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -5850,7 +5850,6 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o | // hval = Z_LVAL_P(dim); | GET_ZVAL_LVAL ZREG_FCARG2, op2_addr } - | SET_EX_OPLINE opline, r0 if (packed_loaded) { | EXT_CALL zend_jit_hash_index_lookup_rw_no_packed, r0 } else { @@ -5970,7 +5969,6 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o } break; case BP_VAR_RW: - | SET_EX_OPLINE opline, r0 if (opline->op2_type != IS_CONST) { | EXT_CALL zend_jit_symtable_lookup_rw, r0 } else { @@ -6015,7 +6013,9 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o |.cold_code |3: } - | SET_EX_OPLINE opline, r0 + if (type != BP_VAR_RW) { + | SET_EX_OPLINE opline, r0 + } | LOAD_ZVAL_ADDR FCARG2a, op2_addr switch (type) { case BP_VAR_R: @@ -6772,6 +6772,7 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 op2_addr = (opline->op2_type != IS_UNUSED) ? OP2_ADDR() : 0; op3_addr = OP1_DATA_ADDR(); + | SET_EX_OPLINE opline, r0 if (op1_info & MAY_BE_REF) { | LOAD_ZVAL_ADDR FCARG1a, op1_addr | IF_NOT_Z_TYPE FCARG1a, IS_REFERENCE, >1 @@ -6781,7 +6782,6 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 | jmp >3 |.cold_code |2: - | SET_EX_OPLINE opline, r0 | EXT_CALL zend_jit_prepare_assign_dim_ref, r0 | test r0, r0 | mov FCARG1a, r0 @@ -6815,7 +6815,6 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 if (op1_info & MAY_BE_NULL) { | IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1 } - | SET_EX_OPLINE opline, r0 | mov FCARG1a, opline->op1.var | EXT_CALL zend_jit_undefined_op_helper, r0 |1: @@ -6901,7 +6900,6 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 | sub r4, 12 | PUSH_ADDR binary_op, r0 |.endif - | SET_EX_OPLINE opline, r0 if (((opline+1)->op1_type & (IS_TMP_VAR|IS_VAR)) && (op1_data_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) { | EXT_CALL zend_jit_assign_op_to_typed_ref_tmp, r0 @@ -6962,7 +6960,6 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, uint3 |7: } - | SET_EX_OPLINE opline, r0 if (Z_REG(op1_addr) != ZREG_FCARG1 || Z_OFFSET(op1_addr) != 0) { | LOAD_ZVAL_ADDR FCARG1a, op1_addr } @@ -12236,6 +12233,9 @@ static int zend_jit_fetch_dim(dasm_State **Dst, op2_addr = (opline->op2_type != IS_UNUSED) ? OP2_ADDR() : 0; + if (opline->opcode == ZEND_FETCH_DIM_RW) { + | SET_EX_OPLINE opline, r0 + } if (op1_info & MAY_BE_REF) { may_throw = 1; | LOAD_ZVAL_ADDR FCARG1a, op1_addr @@ -12246,7 +12246,9 @@ static int zend_jit_fetch_dim(dasm_State **Dst, | jmp >3 |.cold_code |2: - | SET_EX_OPLINE opline, r0 + if (opline->opcode != ZEND_FETCH_DIM_RW) { + | SET_EX_OPLINE opline, r0 + } | EXT_CALL zend_jit_prepare_assign_dim_ref, r0 | test r0, r0 | mov FCARG1a, r0 @@ -12282,7 +12284,6 @@ static int zend_jit_fetch_dim(dasm_State **Dst, if (op1_info & MAY_BE_NULL) { | IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1 } - | SET_EX_OPLINE opline, r0 | mov FCARG1a, opline->op1.var | EXT_CALL zend_jit_undefined_op_helper, r0 |1: @@ -12369,7 +12370,9 @@ static int zend_jit_fetch_dim(dasm_State **Dst, |7: } - | SET_EX_OPLINE opline, r0 + if (opline->opcode != ZEND_FETCH_DIM_RW) { + | SET_EX_OPLINE opline, r0 + } if (Z_REG(op1_addr) != ZREG_FCARG1 || Z_OFFSET(op1_addr) != 0) { | LOAD_ZVAL_ADDR FCARG1a, op1_addr } diff --git a/ext/opcache/tests/jit/fetch_dim_rw_004.phpt b/ext/opcache/tests/jit/fetch_dim_rw_004.phpt new file mode 100644 index 00000000000..7e9b032551e --- /dev/null +++ b/ext/opcache/tests/jit/fetch_dim_rw_004.phpt @@ -0,0 +1,24 @@ +--TEST-- +JIT FETCH_DIM_RW: 004 +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught TypeError: {closure}(): Argument #1 ($y) must be of type y, int given, called in %sfetch_dim_rw_004.php on line 5 and defined in /home/dmitry/php/php8.1/ext/opcache/tests/jit/fetch_dim_rw_004.php:2 +Stack trace: +#0 %sfetch_dim_rw_004.php(5): {closure}(2, 'Undefined varia...', '%s', 5) +#1 {main} + +Next TypeError: Illegal offset type in %sfetch_dim_rw_004.php:5 +Stack trace: +#0 {main} + thrown in %sfetch_dim_rw_004.php on line 5