php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #77287 Opcache literal compaction is incompatible with EXT opcodes
Submitted: 2018-12-12 08:33 UTC Modified: 2019-01-22 11:14 UTC
Votes:9
Avg. Score:4.7 ± 0.7
Reproduced:9 of 9 (100.0%)
Same Version:8 (88.9%)
Same OS:1 (11.1%)
From: someone dot is dot alive at gmail dot com Assigned: nikic (profile)
Status: Closed Package: opcache
PHP Version: 7.3.0 OS: Windows
Private report: No CVE-ID: None
 [2018-12-12 08:33 UTC] someone dot is dot alive at gmail dot com
Description:
------------
Function has 2 arguments. 2nd has a default value. When calling a function it returns an fatal error instead passing second argument as a default value.

Test script:
---------------
Test case is available in zip https://www.jerc.si/wp-content/uploads/2018/12/php7.3.zip
Contains:
- index.php
- init.php (load files)
- PHPDemo/Utils.php (echo's few lines)
- PHPDemo/TestConst.php (simple class instance)

Short preview:
public static function testInput(string $name, int $step = TestConst::STEP_1)
Utils::testInput('abc 1');
Utils::testInput('abc 2', TestConst::STEP_2);
Utils::testInput('abc 3');

Expected result:
----------------
Based on a code in ZIP file.
"Hello world! abc 3 > 1
yes"

Actual result:
--------------
TypeError: Argument 2 passed to PHPDemo\Utils::testInput() must be of the type int, unknown given, called in D:\www\index.php on line 10 in D:\www\PHPDemo\Utils.php on line 6

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-12-12 08:48 UTC] peehaa@php.net
-Status: Open +Status: Feedback
 [2018-12-12 08:48 UTC] peehaa@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc. If the script requires a 
database to demonstrate the issue, please make sure it creates 
all necessary tables, stored procedures etc.

Please avoid embedding huge scripts into the report.
 [2018-12-12 08:58 UTC] someone dot is dot alive at gmail dot com
Test script (below) is copied from zip file.

<?php
namespace PHPDemo;

class TestConst {
    const STEP_1 = 1;
    const STEP_2 = 2;

    public static $persistent = true;
    private static $instance = null;
    private $currentStep = self::STEP_1;

    private function __construct() { }

    public function wasPreviousStepCompleted(int $currentStep) : bool {
        return $this->currentStep >= $currentStep;
    }

    public static function &instance() {
        if (session_id() == '') {
            session_start();
        }
        if (is_null(self::$instance)) {
            self::$instance = new TestConst();
        }
        if (self::$persistent) {
            $_SESSION['TestConst'] = self::$instance;
        } else {
            unset($_SESSION['TestConst']);
        }
        return self::$instance;
    }

    public static function destroyInstance() {
        self::$instance = null;
    }

    public function __wakeup() {
        self::$instance =& $this;
    }
}

class Utils {
    public static function testInput(string $name, int $step = TestConst::STEP_1) {
        var_dump(func_get_args());
        if (empty($name)) {
            return;
        }

        echo 'Hello world! ' . $name . ' > ' . $step . '<br />';

        $test = TestConst::instance();
        if ($test->wasPreviousStepCompleted($step)) {
            echo 'yes';
        } else {
            echo 'no';
        }
        echo '<br />';
    }
}

TestConst::instance();

Utils::testInput('abc 1');
Utils::testInput('abc 2', TestConst::STEP_2);
Utils::testInput('abc 3');
 [2018-12-12 09:11 UTC] peehaa@php.net
Can you limit it to the actual problem code?

There are a lot of random (and seemingly unrelated) things going on in the code. If all that code is actually needed to reproduce please say so. If need please provide the minimal code to reproduce the problem.
 [2018-12-12 10:26 UTC] someone dot is dot alive at gmail dot com
I think i found a problem - when opcache is enabled i get the error. Usually happens when i edit file (e.g. (un)comment TestConst::STEP_2)

This is the shortest code to reproduce:
- no exception at all (e.g. for first 10 requests or it may throw error on first attempt)
- Argument 2 passed to PHPDemo\Utils::testInput() must be of the type int, unknown given
- Argument 2 passed to PHPDemo\Utils::testInput() must be of the type int, object given
- Argument 2 passed to PHPDemo\Utils::testInput() must be of the type int, bool given

<?php
namespace PHPDemo;

class TestConst {
    const STEP_1 = 1;
    const STEP_2 = 2;
}

class Utils {
    public static function testInput(string $name, int $step = TestConst::STEP_1) { }
}

Utils::testInput('abc 1');


------
I deleted all cached files, restarted server
OPCache log (opcache.log_verbosity_level=4)
Wed Dec 12 11:15:22 2018 (33644): Debug Restart Scheduled! Reason: user
Wed Dec 12 11:15:22 2018 (33644): Debug Restarting!
Wed Dec 12 11:17:53 2018 (33644): Message Cached script 'D:\www\demo.php'
Wed Dec 12 11:15:45 2018 (33644): Message Added key 'D:/www/demo.php'
Wed Dec 12 11:18:44 2018 (33644): Message Cached script 'D:\www\demo.php'
Wed Dec 12 11:18:44 2018 (33644): Message Added key 'D:/www/demo.php'
 [2018-12-12 10:31 UTC] peehaa@php.net
-Status: Feedback +Status: Open
 [2018-12-12 10:44 UTC] peehaa@php.net
-Package: Unknown/Other Function +Package: opcache
 [2018-12-12 10:59 UTC] nikic@php.net
Can't repro on Ubuntu, possibly Windows only.

The resolved default value for the 2nd arg will be stored in the RT cache, so maybe there is an invalidation problem.
 [2018-12-17 00:40 UTC] andrew at fw dot net dot nz
I encountered the same error after upgrading php-fpm from 7.2 to 7.3 on Ubuntu 18.04. An argument with a default parameter threw a type error "unknown given" when the callee did not provide the argument at all.
I ran opcache_reset() which resolved it.

A google search found another mention of the same error in 7.3 here:
https://github.com/nextcloud/server/issues/11868
 [2018-12-26 00:49 UTC] pirogen at protonmail dot com
I've encountered this as well after upgrading from 7.2 to 7.3 on Debian Testing. Unfortunately, I can't seem to reproduce it in a minimal fashion; it only occurs in a project with rather large graph of inter-dependent objects.

The bug manifests itself with class methods that use constants (can be a class constant, built-in constant or user-defined global constant) as default parameter values, i.e.:

public function someMethod($some_param=SOME_CONSTANT) {}

When someMethod is called with no arguments, $some_param *sometimes* (more often than not, but not always) receives a value that var_dump() identifies as NFC. Which, if passed down to a function or method that expects a specific type, throws a "[function] expects parameter [num] to be [type], unknown given" error OP mentions.
 [2018-12-28 11:35 UTC] pirogen at protonmail dot com
It looks like the bug only occurs with *both* opcache and xdebug enabled. Disabling *either* makes the issue go away.
 [2019-01-02 12:20 UTC] nikic@php.net
-Assigned To: +Assigned To: nikic
 [2019-01-02 12:20 UTC] nikic@php.net
Could it be that you're on a 32-bit system (or use a 32-bit PHP build)?
 [2019-01-02 13:15 UTC] nikic@php.net
If you are using a 32-bit build, then I've committed a possible fix in https://github.com/php/php-src/commit/325a1139744413420a62d3006c04914587628810. If not, then the issue must be somewhere else...
 [2019-01-03 07:14 UTC] someone dot is dot alive at gmail dot com
My setup:
Windows 10, build 17763, x64
Apache 2.4.34, x64
PHP x64 TS
Xdebug v2.7.0beta1
 [2019-01-03 08:29 UTC] nikic@php.net
Thanks. So no 32-bit, but also using the combination of opcache and xdebug.
 [2019-01-11 11:27 UTC] stevenlewis at gowebprint dot com
I can confirm the same problem on CentOS 7.6 x64

I can also confirm it only happens when xdebug and opcache are enabled

I also get a segfualt logged to syslog that look like

Jan 11 11:17:41 dev kernel: php-fpm[27762]: segfault at ffffffffffffffff ip 000056373fb92058 sp 00007ffffbfdc968 error 7 in php-fpm[56373fab5000+14b000]
Jan 11 11:17:41 dev kernel: php-fpm[27760]: segfault at ffffffffffffffff ip 000056373fe17718 sp 00007ffffbfdced0 error 7 in php-fpm[56373fe00000+113000]
Jan 11 11:17:45 dev kernel: php-fpm[27764]: segfault at 100000001 ip 000056373fb92058 sp 00007ffffbfdc968 error 6 in php-fpm[56373fab5000+14b000]
Jan 11 11:17:51 dev kernel: php-fpm[27763]: segfault at 100000001 ip 000056373fb92058 sp 00007ffffbfdc968 error 6 in php-fpm[56373fab5000+14b000]
Jan 11 11:17:54 dev kernel: php-fpm[27768]: segfault at 2 ip 000056373fb92058 sp 00007ffffbfdd748 error 6 in php-fpm[56373fab5000+14b000]
 [2019-01-14 09:28 UTC] nikic@php.net
-Assigned To: nikic +Assigned To: derick
 [2019-01-14 09:28 UTC] nikic@php.net
Derick, does this issue sound familiar?
 [2019-01-22 11:07 UTC] nikic@php.net
-Assigned To: derick +Assigned To: nikic
 [2019-01-22 11:07 UTC] nikic@php.net
I believe the bug here is actually in opcache and xdebug only triggers it by enabling EXT opcodes.
 [2019-01-22 11:14 UTC] nikic@php.net
-Summary: Fatal error: Uncaught TypeError +Summary: Opcache literal compaction is incompatible with EXT opcodes
 [2019-01-22 11:30 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=76760901fabf8ff53c8dfb4ddf7ca703c5a12b79
Log: Fixed bug #77287
 [2019-01-22 11:30 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 [2019-02-05 12:24 UTC] cmb@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=80b17a73ae2e203f26bb3f0da423508596d71f1f
Log: Fixed bug #77287
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 13:01:25 2019 UTC