Bug #76281 [Ver->Ana]: Opcache causes incorrect "undefined variable" errors
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)