php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #68765 Optimisation of constant definitions can cause incorrect output.
Submitted: 2015-01-07 12:01 UTC Modified: 2017-06-23 15:50 UTC
Votes:9
Avg. Score:3.3 ± 1.2
Reproduced:8 of 8 (100.0%)
Same Version:3 (37.5%)
Same OS:6 (75.0%)
From: axel dot ml at warenform dot net Assigned: nikic (profile)
Status: Closed Package: opcache
PHP Version: 5.6.4 OS: Linux x86_64
Private report: No CVE-ID: None
 [2015-01-07 12:01 UTC] axel dot ml at warenform dot net
Description:
------------
With active opcache following problems occurs:

If constants.php is called first the output is:
1
1
1
1
1
which is correct.
If constants-include.php is called the output is:
4
which is also correct.
If constants.php is called afterwards the output is:
1
1
1
4
1
which is wrong.

The line is @define('SOME_CONSTANT', 4) is conditionally because of the "@" and must not be evaluated by opcache but on runtime.

If the line is rewritten as:
if (!defined('SOME_CONSTANT')) define('SOME_CONSTANT', 4);
everything works as expected.

Thank you for fixing this issue.

Test script:
---------------
FILE: constants-include.php
@define('SOME_CONSTANT', 4);
echo SOME_CONSTANT.'<br>'.PHP_EOL;

FILE: constants.php
define('SOME_CONSTANT', 1);
echo SOME_CONSTANT.'<br>'.PHP_EOL;
@define('SOME_CONSTANT', 2);
echo SOME_CONSTANT.'<br>'.PHP_EOL;
@define('SOME_CONSTANT', 3);
echo SOME_CONSTANT.'<br>'.PHP_EOL;
include('./constants-include.php');
echo SOME_CONSTANT.'<br>'.PHP_EOL;

Expected result:
----------------
1
1
1
1
1


Actual result:
--------------
1
1
1
4
1


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-01-07 15:58 UTC] leigh@php.net
-Status: Open +Status: Not a bug
 [2015-01-07 15:58 UTC] leigh@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

The @ operator is not a conditional construct. It prevents any error from being displayed, it does not prevent the statement from executing.

Checking the constant with `if (!defined(...))` is the correct way to handle this situation.
 [2015-01-07 18:52 UTC] axel dot ml at warenform dot net
I admit using an "@" here is misleading. But if you omit all "@"s the problem is still the same: The code behaves different, when turning opcache on. The seems to be a bug for me.
 [2015-01-07 19:07 UTC] aharvey@php.net
-Status: Not a bug +Status: Re-Opened
 [2015-01-07 19:23 UTC] leigh@php.net
-Summary: Commands with @ must not be evaluated by opcache +Summary: Optimisation of constant definitions can cause incorrect output.
 [2015-01-07 19:23 UTC] leigh@php.net
Apologies I didn't read properly.

It seems to me this is unrelated to the @ operator at all then (yes the current bug title is misleading - I'll try and think of something more appropriate), as you state yourself, if you omit all of the @ operators the problem persists.

I suspect there is some kind of optimisation being performed, and OpCache noticing that the include file has not changed, simply spits out the optimised output even though the execution conditions have changed.
 [2015-03-13 11:39 UTC] v dot leborgne at shop-application dot com
I experience the same issue with php 5.6.6 : 

myscript.php :
define('FOO','hello');
include('somefile.php');
echo ANOTHER_FOO;

somefile.php :
define('FOO','hi');
define('ANOTHER_FOO',FOO.' world');


myscript.php prints :

    in PHP<5.6 : "hello world"
    in PHP5.6 : "hi world"
 [2015-03-13 11:49 UTC] v dot leborgne at shop-application dot com
I've done some more tests :

PHP 5.6.6 and opcache disabled : "hello world"
PHP 5.6.6 and opcache enabled: "hi world"
PHP 5.5.22 and opcache disabled : "hello world"
PHP 5.5.22 and opcache enabled : "hello world"
 [2017-06-23 15:50 UTC] nikic@php.net
-Status: Re-Opened +Status: Closed -Assigned To: +Assigned To: nikic
 [2017-06-23 15:50 UTC] nikic@php.net
This has been fixed at some point with the addition of the ZEND_OPTIMIZER_PASS_15 ("collect constants") flag, which is disabled by default.
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Thu Dec 02 13:03:33 2021 UTC