Bug #68185 [Asn]: 'PHP Fatal error: Inconsistent insteadof definition.' - incorrectly triggered
| From: | jpauli@php.net | Date: | Wed, 29 Oct 2014 13:43:53 +0000 |
| Subject: | Bug #68185 [Asn]: 'PHP Fatal error: Inconsistent insteadof definition.' - incorrectly triggered | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-188360@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=68185&edit=1
ID: 68185
Updated by: jpauli@php.net
Reported by: marc at dotfive dot co dot uk
Summary: 'PHP Fatal error: Inconsistent insteadof
definition.' - incorrectly triggered
Status: Assigned
Type: Bug
Package: Class/Object related
Operating System: Debian Wheezy/Jessie
PHP Version: 5.6.1
Assigned To: aharvey
Block user comment: N
Private report: N
New Comment:
This effectively fixes it.
The fact that it got random part is true.
Having i instead of j in the loop does add a very different meaning to the code.
Depending on random, you effectively can hit this bug, this is why having a test case for it is very
hard.
Anyway, this patch fixes the behavior :
https://github.com/jpauli/php-src/compare/68185
Previous Comments:
------------------------------------------------------------------------
[2014-10-08 09:14:33] marc at dotfive dot co dot uk
Description:
------------
'PHP Fatal error: Inconsistent insteadof definition.' - This error is triggered
incorrectly and very unpredictably on classes with many traits. Reproducing this bug is very
difficult, as the outcome is affected by seemingly irrelevant things. This has been found in
versions 5.4 through to 5.6.1 and appears to have been introduced by commit
520d07d86a7520c970e18480ed0237c6253bd097, which fixed Bug #61052: "missing error check in trait
'insteadof' clause"
This inconsistant behaviour appears to be caused by an incorrect index when checking if the included
trait method is in exclude_from_classes. In the code below from zend_compile.c
cur_precedence->exclude_from_classes[i] should, I believe, be
cur_precedence->exclude_from_classes[j] (i.e. the 'i' should be a 'j'):
zend_compile.c
----------------------------
/* make sure that the trait method is not from a class mentioned in
exclude_from_classes, for consistency */
if (cur_precedence->trait_method->ce == cur_precedence->exclude_from_classes[i]) {
zend_error(E_COMPILE_ERROR,
"Inconsistent insteadof definition. "
Test script:
---------------
The following script is split across two files, 'test' and 'class.php'. I have
been unable to create a script in a single file that incorrectly triggers the error. The first file,
test, creates a bunch of empty classes and includes class.php, which defines a classes with traits
and uses 'insteadof'. Changing the number of empty classes that are created in test
changes whether or not the error triggers, as does changing the number of traits in class.php. Even
seemingly irrelevant things change whether the error triggers; adding something like an
'echo' at the beginning of the script, or running the script from a different directory
changes this behaviour.
test:
------------------------
#!/usr/bin/php -q
<?php
$i = 17;
while ($i--) {
eval('class c' . $i . ' {}');
}
require_once("class.php");
die("End");
class.php:
-----------------------
<?php
namespace SPACE;
trait trait0 { public function methodName() {} }
trait trait1 { public function methodName() {} }
trait trait2 { public function methodName() {} }
trait trait3 { public function methodName() {} }
trait trait4 { public function methodName() {} }
trait trait5 { public function methodName() {} }
trait trait6 { public function methodName() {} }
trait trait7 { public function methodName() {} }
class c {
use trait0,
trait1,
trait2,
trait3,
trait4,
trait5,
trait6,
trait7
{
trait0::methodName insteadof trait1;
trait0::methodName insteadof trait2;
trait0::methodName insteadof trait3;
trait0::methodName insteadof trait4;
trait0::methodName insteadof trait5;
trait0::methodName insteadof trait6;
trait0::methodName insteadof trait7;
}
}
Expected result:
----------------
# ./test
End
Actual result:
--------------
# ./test
PHP Fatal error: Inconsistent insteadof definition. The method methodName is to be used from
SPACE\trait0, but SPACE\trait0 is also on the exclude list in /root/class.php on line 79
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=68185&edit=1