diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index f8a24c18c242a..a5d35c69598d1 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -17195,7 +17195,10 @@ static void jit_frameless_icall1(zend_jit_ctx *jit, const zend_op *opline, uint3 ir_ref op1_ref = jit_ZVAL_ADDR(jit, op1_addr); jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { - zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + op1_info &= ~MAY_BE_UNDEF; + op1_info |= MAY_BE_NULL; + op1_addr = ZEND_ADDR_REF_ZVAL(op1_ref); } if (op1_info & MAY_BE_REF) { op1_ref = jit_ZVAL_DEREF_ref(jit, op1_ref); @@ -17237,10 +17240,16 @@ static void jit_frameless_icall2(zend_jit_ctx *jit, const zend_op *opline, uint3 ir_ref op2_ref = jit_ZVAL_ADDR(jit, op2_addr); jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { - zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + op1_info &= ~MAY_BE_UNDEF; + op1_info |= MAY_BE_NULL; + op1_addr = ZEND_ADDR_REF_ZVAL(op1_ref); } if (opline->op2_type == IS_CV && (op2_info & MAY_BE_UNDEF)) { - zend_jit_zval_check_undef(jit, op2_ref, opline->op2.var, opline, 1); + op2_ref = zend_jit_zval_check_undef(jit, op2_ref, opline->op2.var, opline, 1); + op2_info &= ~MAY_BE_UNDEF; + op2_info |= MAY_BE_NULL; + op2_addr = ZEND_ADDR_REF_ZVAL(op2_ref); } if (op1_info & MAY_BE_REF) { op1_ref = jit_ZVAL_DEREF_ref(jit, op1_ref); @@ -17296,13 +17305,22 @@ static void jit_frameless_icall3(zend_jit_ctx *jit, const zend_op *opline, uint3 ir_ref op3_ref = jit_ZVAL_ADDR(jit, op3_addr); jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL); if (opline->op1_type == IS_CV && (op1_info & MAY_BE_UNDEF)) { - zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + op1_ref = zend_jit_zval_check_undef(jit, op1_ref, opline->op1.var, opline, 1); + op1_info &= ~MAY_BE_UNDEF; + op1_info |= MAY_BE_NULL; + op1_addr = ZEND_ADDR_REF_ZVAL(op1_ref); } if (opline->op2_type == IS_CV && (op2_info & MAY_BE_UNDEF)) { - zend_jit_zval_check_undef(jit, op2_ref, opline->op2.var, opline, 1); + op2_ref = zend_jit_zval_check_undef(jit, op2_ref, opline->op2.var, opline, 1); + op2_info &= ~MAY_BE_UNDEF; + op2_info |= MAY_BE_NULL; + op2_addr = ZEND_ADDR_REF_ZVAL(op2_ref); } if ((opline+1)->op1_type == IS_CV && (op1_data_info & MAY_BE_UNDEF)) { - zend_jit_zval_check_undef(jit, op3_ref, (opline+1)->op1.var, opline, 1); + op3_ref = zend_jit_zval_check_undef(jit, op3_ref, (opline+1)->op1.var, opline, 1); + op1_data_info &= ~MAY_BE_UNDEF; + op1_data_info |= MAY_BE_NULL; + op3_addr = ZEND_ADDR_REF_ZVAL(op3_ref); } if (op1_info & MAY_BE_REF) { op1_ref = jit_ZVAL_DEREF_ref(jit, op1_ref); diff --git a/ext/opcache/tests/jit/gh16009.phpt b/ext/opcache/tests/jit/gh16009.phpt new file mode 100644 index 0000000000000..6c1d6b6984d88 --- /dev/null +++ b/ext/opcache/tests/jit/gh16009.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-16009 (Segmentation fault with frameless functions and undefined CVs) +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=1012 +--FILE-- + +--EXPECTF-- +Warning: Undefined variable $value in %s on line %d + +Fatal error: Uncaught TypeError: testMin2Second(): Return value must be of type int, null returned in %s:%d +Stack trace: +#0 %s(%d): testMin2Second() +#1 {main} + thrown in %s on line %d