diff --git a/NEWS b/NEWS index dd28760928e..8f6738078ab 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ PHP NEWS - Core: . Fixed line number of JMP instruction over else block. (ilutov) + . Fixed use-of-uninitialized-value with ??= on assert. (ilutov) 06 Jul 2023, PHP 8.3.0alpha3 diff --git a/Zend/tests/gh11580.phpt b/Zend/tests/gh11580.phpt new file mode 100644 index 00000000000..194c8b5a1aa --- /dev/null +++ b/Zend/tests/gh11580.phpt @@ -0,0 +1,13 @@ +--TEST-- +GH-11580: assert() with ??= operator can lead to use-of-uninitialized-value +--INI-- +zend.assertions=0 +--FILE-- + +--EXPECTF-- +Fatal error: Uncaught Error: Undefined constant "y" in %s:%d +Stack trace: +#0 {main} + thrown in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index ea71e075f8c..85f19d32038 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4203,6 +4203,10 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string zend_op *opline; uint32_t check_op_number = get_next_op_number(); + /* Assert expression may not be memoized and reused as it may not actually be evaluated. */ + int orig_memoize_mode = CG(memoize_mode); + CG(memoize_mode) = ZEND_MEMOIZE_NONE; + zend_emit_op(NULL, ZEND_ASSERT_CHECK, NULL, NULL); if (fbc && fbc_is_finalized(fbc)) { @@ -4236,6 +4240,8 @@ static void zend_compile_assert(znode *result, zend_ast_list *args, zend_string opline = &CG(active_op_array)->opcodes[check_op_number]; opline->op2.opline_num = get_next_op_number(); SET_NODE(opline->result, result); + + CG(memoize_mode) = orig_memoize_mode; } else { if (!fbc) { zend_string_release_ex(name, 0);