|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[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;
}
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Thu Oct 30 22:00:01 2025 UTC |
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'));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.