mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Fix circumvented type check with return by ref + finally
Fixes GH-18736 Closes GH-19172
This commit is contained in:
parent
a96b05e63f
commit
d0fad34230
3 changed files with 38 additions and 0 deletions
2
NEWS
2
NEWS
|
@ -17,6 +17,8 @@ PHP NEWS
|
||||||
delegated Generator). (Arnaud)
|
delegated Generator). (Arnaud)
|
||||||
. Fixed bug GH-19326 (Calling Generator::throw() on a running generator with
|
. Fixed bug GH-19326 (Calling Generator::throw() on a running generator with
|
||||||
a non-Generator delegate crashes). (Arnaud)
|
a non-Generator delegate crashes). (Arnaud)
|
||||||
|
. Fixed bug GH-18736 (Circumvented type check with return by ref + finally).
|
||||||
|
(ilutov)
|
||||||
|
|
||||||
- FTP:
|
- FTP:
|
||||||
. Fix theoretical issues with hrtime() not being available. (nielsdos)
|
. Fix theoretical issues with hrtime() not being available. (nielsdos)
|
||||||
|
|
24
Zend/tests/gh18736.phpt
Normal file
24
Zend/tests/gh18736.phpt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
--TEST--
|
||||||
|
GH-18736: Circumvented type check with return by ref + finally
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function &test(): int {
|
||||||
|
$x = 0;
|
||||||
|
try {
|
||||||
|
return $x;
|
||||||
|
} finally {
|
||||||
|
$x = 'test';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$x = &test();
|
||||||
|
var_dump($x);
|
||||||
|
} catch (Error $e) {
|
||||||
|
echo $e->getMessage(), "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
test(): Return value must be of type int, string returned
|
|
@ -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);
|
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);
|
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,
|
opline = zend_emit_op(NULL, by_ref ? ZEND_RETURN_BY_REF : ZEND_RETURN,
|
||||||
&expr_node, NULL);
|
&expr_node, NULL);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue