diff --git a/NEWS b/NEWS index e89bc61148d..727b25f0521 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,8 @@ PHP NEWS delegated Generator). (Arnaud) . Fixed bug GH-19326 (Calling Generator::throw() on a running generator with a non-Generator delegate crashes). (Arnaud) + . Fixed bug GH-18736 (Circumvented type check with return by ref + finally). + (ilutov) - FTP: . Fix theoretical issues with hrtime() not being available. (nielsdos) diff --git a/Zend/tests/gh18736.phpt b/Zend/tests/gh18736.phpt new file mode 100644 index 00000000000..f397ee39a31 --- /dev/null +++ b/Zend/tests/gh18736.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-18736: Circumvented type check with return by ref + finally +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +test(): Return value must be of type int, string returned diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 41113e2f005..6c8577cef58 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5201,8 +5201,20 @@ static void zend_compile_return(zend_ast *ast) /* {{{ */ expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, 0); } + uint32_t opnum_before_finally = get_next_op_number(); + zend_handle_loops_and_finally((expr_node.op_type & (IS_TMP_VAR | IS_VAR)) ? &expr_node : NULL); + /* Content of reference might have changed in finally, repeat type check. */ + if (by_ref + /* Check if any opcodes were emitted since the last return type check. */ + && opnum_before_finally != get_next_op_number() + && !is_generator + && (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) { + zend_emit_return_type_check( + expr_ast ? &expr_node : NULL, CG(active_op_array)->arg_info - 1, 0); + } + opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN, &expr_node, NULL);