Bug #72188 [Ver]: Nested try/finally blocks losing return value
| From: | nikic@php.net | Date: | Wed, 11 May 2016 14:30:00 +0000 |
| Subject: | Bug #72188 [Ver]: Nested try/finally blocks losing return value | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-201016@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=72188&edit=1
ID: 72188
Updated by: nikic@php.net
Reported by: lee at saferite dot com
Summary: Nested try/finally blocks losing return value
Status: Verified
Type: Bug
Package: Unknown/Other Function
Operating System: Ubuntu 14.04
PHP Version: 7.0.6
Assigned To: nikic
Block user comment: N
Private report: N
New Comment:
So, as I understand it the problem is that the FAST_CALL<FROM_FINALLY> of the inner finally
block will indiscriminately set the fast_call opline to the FAST_CALL of the outer finally block,
even though this is not necessarily the FAST_CALL that was actually used to enter it (e.g. in this
instance).
I was wondering why this worked on PHP 5.6 as IIRC the handling wasn't very different. It looks
like it's just an accident of fate that this particular code works there. This similar example
doesn't: https://3v4l.org/DsLLE
The only solution to this I see is to use different fast_call temporaries for each nesting level of
finally-in-finally. We also need this to solve a similar issue with exceptions, though I can't
seem to find the bug report for that just now (maybe in private discussions?).
Previous Comments:
------------------------------------------------------------------------
[2016-05-11 07:48:31] laruence@php.net
@nikic what do you think ? I don't see a easy to fix it..
------------------------------------------------------------------------
[2016-05-11 07:46:19] laruence@php.net
fast_call in before finally overfide the return address set by the fast_call before zend_return.
------------------------------------------------------------------------
[2016-05-10 19:11:04] lee at saferite dot com
Description:
------------
When you next a try/finally inside of a finally block it causes the return value from the outer try
block to be lost.
Test script:
---------------
<?php
function test() {
try {
return 5;
} finally {
try {
// NOOP
} finally {
// NOOP
}
}
}
$a = test();
if($a !== 5) {
echo "FAILED: expected 5, received ", var_export($a), PHP_EOL;
} else {
echo "Passed", PHP_EOL;
}
Expected result:
----------------
The call to test() should be seeing an int value of 5.
Actual result:
--------------
5.5.16-5.6.21 -- Works as expected
5.5.0-5.5.15 -- Exit code of 137 (SIGKILL)
7.0.0-7.0.6 -- The outer return value is lost and a null is returned.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=72188&edit=1