diff --git a/NEWS b/NEWS index cea3e9b1db1..6d3f3b7d82d 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,8 @@ PHP NEWS . Fixed bug GH-19934 (CGI with auto_globals_jit=0 causes uouv). (ilutov) . Fixed bug GH-20073 (Assertion failure in WeakMap offset operations on reference). (nielsdos) + . Fixed bug GH-20085 (Assertion failure when combining lazy object + get_properties exception with foreach loop). (nielsdos) 09 Oct 2025, PHP 8.4.14 diff --git a/Zend/tests/lazy_objects/gh20085.phpt b/Zend/tests/lazy_objects/gh20085.phpt new file mode 100644 index 00000000000..5624f71ea8b --- /dev/null +++ b/Zend/tests/lazy_objects/gh20085.phpt @@ -0,0 +1,25 @@ +--TEST-- +GH-20085 (Assertion failure when combining lazy object get_properties exception with foreach loop) +--FILE-- +a = 1; + } +} +$obj = new C; +$reflector = new ReflectionClass(C::class); +foreach ($obj as &$value) { + $obj = $reflector->newLazyGhost(function ($obj) { + throw new Error; + }); +} +echo !obj; +?> +--EXPECTF-- +Fatal error: Uncaught Error in %s:%d +Stack trace: +#0 %s(%d): {closure:%s:%d}(Object(C)) +#1 {main} + thrown in %s on line %d diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index c40dd4cc8ed..039d9679848 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7275,7 +7275,7 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY, JMP_ADDR) while (1) { if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { /* reached end of iteration */ - ZEND_VM_C_GOTO(fe_fetch_w_exit); + ZEND_VM_C_GOTO(fe_fetch_w_exit_exc); } pos++; value = &p->val; @@ -7371,6 +7371,7 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY, JMP_ADDR) } } else { zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array)); +ZEND_VM_C_LABEL(fe_fetch_w_exit_exc): if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); HANDLE_EXCEPTION(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a9f33224d82..d6ee850839a 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -23173,7 +23173,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z while (1) { if (UNEXPECTED(pos >= fe_ht->nNumUsed)) { /* reached end of iteration */ - goto fe_fetch_w_exit; + goto fe_fetch_w_exit_exc; } pos++; value = &p->val; @@ -23269,6 +23269,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z } } else { zend_error(E_WARNING, "foreach() argument must be of type array|object, %s given", zend_zval_value_name(array)); +fe_fetch_w_exit_exc: if (UNEXPECTED(EG(exception))) { UNDEF_RESULT(); HANDLE_EXCEPTION();