php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76281 Opcache causes incorrect "undefined variable" errors
Submitted: 2018-04-27 19:27 UTC Modified: 2018-04-27 20:02 UTC
From: woody dot gilk at gmail dot com Assigned:
Status: Closed Package: opcache
PHP Version: 7.2.5 OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: woody dot gilk at gmail dot com
New email:
PHP Version: OS:

 

 [2018-04-27 19:27 UTC] woody dot gilk at gmail dot com
Description:
------------
% php --version
PHP 7.2.4-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Apr  5 2018 08:53:57) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.4-1+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies

PHP 7.2.5 is not yet available for my distro.

The bug does NOT appear on PHP 7.1.16.

When running the test script (part of a larger class) the following error always occurs:

E_NOTICE: Undefined variable: user_sub_resource on line 37

For obvious reasons, this is an impossible situation because the variable is defined and can only be a boolean.

When I disable opcache the problem disappears and everything works correctly.

Test script:
---------------
$user_sub_resource = in_array($action, array('get_securityquestions', 'get_status', 'get_groupstats'));

$user_id = null;
if ($user_sub_resource && isset($r['user_id'])) { // !! NO ERROR HERE !!
    $user_id = $r['user_id'];
}
else if (isset($r['id']))  {
    $user_id = $r['id'];
}

if ($user_sub_resource) { // !! ERROR HAPPENS HERE !!
    if ($action === 'get_securityquestions' && !$this->isRequestor($r['user_id'])) {
        $this->violation('can\'t get another user\'s security information');
    }

    return $perms;
}


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-04-27 19:35 UTC] woody dot gilk at gmail dot com
One additional comment to add:

When I change the if() conditions to:

$user_sub_resource === true

for each reference to $user_sub_resource then the error goes away.

The problem also goes away if I change the line AFTER the problem to:

if ($action === 'get_securityquestions' && !$this->isRequestor($user_id))

Though I have absolutely no idea why that is the case.
 [2018-04-27 19:54 UTC] nikic@php.net
-Status: Open +Status: Verified
 [2018-04-27 19:54 UTC] nikic@php.net
I can reproduce with the following code:

<?php error_reporting(E_ALL);

function test($r, $action) {
    $user_sub_resource = in_array($action, array('get_securityquestions', 'get_status', 'get_groupstats'));

    $user_id = null;
    if ($user_sub_resource && isset($r['user_id'])) {
        $user_id = $r['user_id'];
    }
    else if (isset($r['id']))  {
        $user_id = $r['id'];
    }

    if ($user_sub_resource) {
        return 'foo';
    }

    return 'bar';
}

var_dump(test(['user_id' => 1, 'id' => 2], 'foo'));
 [2018-04-27 20:02 UTC] nikic@php.net
-Status: Verified +Status: Analyzed
 [2018-04-27 20:02 UTC] nikic@php.net
In the DFA pass we end up going from

            #6.T4 [bool] = IN_ARRAY 0 #5.CV1($action) [any] array(...)
            ASSIGN #2.CV2($user_sub_resource) NOVAL [undef] -> #7.CV2($user_sub_resource) [bool] #6.T4 [bool]
            NOP
            JMPZ #7.CV2($user_sub_resource) [bool] BB3

to

            #7.CV2($user_sub_resource) [bool] = IN_ARRAY 0 #5.CV1($action) [any] array(...)
            JMPZ #7.CV2($user_sub_resource) [bool] BB3

which drops the NOP necessary for smart branch inhibition.

The issue seems to be that the NOP elimination only checks for the pattern smart-branch-op NOP JMPZ/NZ, however in this case there will be two NOPs between the IN_ARRAY and the JMPZ, which is not detected as a smart branch.
 [2018-04-27 20:27 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=6738d19fb80b8696f163cae4b9c114c247606daa
Log: Fix bug #76281
 [2018-04-27 20:27 UTC] nikic@php.net
-Status: Analyzed +Status: Closed
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 15:01:30 2024 UTC