Bug #76281 [Ver->Ana]: Opcache causes incorrect "undefined variable" errors

From: Date: Fri, 27 Apr 2018 20:02:15 +0000
Subject: Bug #76281 [Ver->Ana]: Opcache causes incorrect "undefined variable" errors
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-214950@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=76281&edit=1

 ID:                 76281
 Updated by:         nikic@php.net
 Reported by:        woody dot gilk at gmail dot com
 Summary:            Opcache causes incorrect "undefined variable" errors
-Status:             Verified
+Status:             Analyzed
 Type:               Bug
 Package:            opcache
 Operating System:   Linux
 PHP Version:        7.2.5
 Block user comment: N
 Private report:     N

 New Comment:

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.


Previous Comments:
------------------------------------------------------------------------
[2018-04-27 19:54:07] 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 19:35:30] 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:27:46] 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;
}



------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=76281&edit=1


Thread (5 messages)

« previous php.bugs (#214950) next »