php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #72132 isset() sometimes returns FALSE when TRUE is expected
Submitted: 2016-04-30 10:25 UTC Modified: 2016-04-30 19:22 UTC
From: holger dot schletz at web dot de Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 7.0.6 OS: Arch Linux, Kernel 4.5.1-1-ARCH
Private report: No CVE-ID: None
 [2016-04-30 10:25 UTC] holger dot schletz at web dot de
Description:
------------
This seems to be a regression with PHP 7.0.6. The problem does not occur when I downgrade to 7.0.5.

The problem is difficult to reproduce. The test script below will most likely behave correctly, but in some very specific context, a similar case will fail, and the failure is reproducible then.


Test script:
---------------
$var['a']['b'] = 'c';
var_dump($var['a']['b']);
var_dump(isset($var['a']['b']));


Expected result:
----------------
string(1) "c"
bool(true)


Actual result:
--------------
string(1) "c"
bool(false)


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-04-30 10:38 UTC] nikic@php.net
-Status: Open +Status: Not a bug
 [2016-04-30 10:38 UTC] nikic@php.net
The issue you are (very likely) hitting, is that starting with PHP 7.0.6 __isset() and offsetExists() will be called for each access level in the expression. So in isset($var['a']['b']), if $var is an ArrayAccess object, you will now see a call to offsetExists($var, 'a'), where none occurred previously. If you don't have a correct offsetExists() implementation, this may lead to the described result.
 [2016-04-30 11:05 UTC] holger dot schletz at web dot de
You are right! I didn't realize that I was working with an ArrayObject instead of a real array. In my case, it was a PHPUnit mock object where the offsetSet method was not stubbed because it didn't have to before. Adding a stub fixed it.

The change might break a lot of edge cases that got away with the previous behavior - mock objects that did not have to deal with those PHP internals before being a not too uncommon case. Could this possible BC break be pointed out in the changelog?
 [2016-04-30 19:22 UTC] holger dot schletz at web dot de
While the error cause is definitely on the application side, the observed behavior is inconsistent. As a future improvement, what about checking the offsetExists() result and generating at least a warning if it is not a boolean? While validating correctness of the result is out of PHP's scope, this would at least ensure that SOMETHING is implemented.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 17:01:29 2024 UTC