Exception not properly caught when opcache enabled
| Bug #65665 | Exception not properly caught when opcache enabled | ||||
|---|---|---|---|---|---|
| Submitted: | 2013-09-13 00:15 UTC | Modified: | 2013-09-15 06:06 UTC | ||
| From: | ryan dot brothers at gmail dot com | Assigned: | dmitry (profile) | ||
| Status: | Closed | Package: | opcache | ||
| PHP Version: | 5.5.3 | OS: | Linux | ||
| Private report: | No | CVE-ID: | None | ||
[2013-09-13 00:15 UTC] ryan dot brothers at gmail dot com
Description:
------------
When running the following script with opcache enabled, the exception is not caught by the correct catch block. The exception should be caught by the 'caught by 1' block, but it is instead caught by the 'caught by 2' block. Disabling opcache causes the exception to be caught in the correct block.
Run the script with:
php -n -d zend_extension=opcache.so -d opcache.enable_cli=1 script.php
Test script:
---------------
<?php
try
{
switch (1)
{
case 0:
try
{
}
catch (Exception $e)
{
}
break;
case 1:
try
{
throw new Exception('aaa');
}
catch (Exception $e)
{
echo 'caught by 1';
exit;
}
break;
}
}
catch (Exception $e)
{
echo 'caught by 2';
exit;
}
Expected result:
----------------
caught by 1
Actual result:
--------------
caught by 2
Patches
Pull Requests
History
AllCommentsChangesGit/SVN commits
[2013-09-13 15:31 UTC] jpauli@php.net
[2013-09-13 17:16 UTC] Danack at basereality dot com
[2013-09-14 06:58 UTC] krakjoe@php.net
[2013-09-15 06:06 UTC] laruence@php.net
Hey: I got a different fix: $ git diff diff --git a/Optimizer/block_pass.c b/Optimizer/block_pass.c index b8c3814..fd76322 100644 --- a/Optimizer/block_pass.c +++ b/Optimizer/block_pass.c @@ -1278,8 +1278,17 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array) if (op_array->last_try_catch) { int i; for (i = 0; i< op_array->last_try_catch; i++) { - op_array->try_catch_array[i].try_op = cfg->try[i]- >start_opline - new_opcodes; - op_array->try_catch_array[i].catch_op = cfg->catch[i]- >start_opline - new_opcodes; + if (cfg->try[i]->access) { + op_array->try_catch_array[i].try_op = cfg->try[i]- >start_opline - new_opcodes; + } else { + op_array->try_catch_array[i].try_op = 0; + } + + if (cfg->catch[i]->access) { + op_array->try_catch_array[i].catch_op = cfg- >catch[i]->start_opline - new_opcodes; + } else { + op_array->try_catch_array[i].catch_op = 0; + } } efree(cfg->try); efree(cfg->catch); dmitry, could you please verify this? thanks