Edit report at http://bugs.php.net/bug.php?id=53971&edit=1

 ID:                 53971
 Updated by:         dtajchre...@php.net
 Reported by:        david at frankieandshadow dot com
 Summary:            isset() and empty() produce apparently spurious
                     runtime error
-Status:             Open
+Status:             Bogus
 Type:               Bug
 Package:            Arrays related
 Operating System:   Linux, Redhat Enterprise
 PHP Version:        5.3.5
 Block user comment: N
 Private report:     N

 New Comment:

$obj->m is an empty string. You try to access a non-integer offset.
Non-integer 

offsets are converted to 

integers. So in other words:

$obj->m['a'] becomes $obj->m[0]

$obj->m is an empty string and $obj->m[0] doesn't exist

This behavior is documented here: 

http://us.php.net/manual/en/language.types.string.php



"Warning

Writing to an out of range offset pads the string with spaces.
Non-integer types 

are converted to integer. 

Illegal offset type emits E_NOTICE. Negative offset emits E_NOTICE in
write but 

reads empty string. Only the 

first character of an assigned string is used. Assigning empty string
assigns 

NUL byte."



Simplifying the problem: http://codepad.org/G31wr4oJ


Previous Comments:
------------------------------------------------------------------------
[2011-02-09 13:12:44] david at frankieandshadow dot com

Description:
------------
First, apologies, this is 5.3.3. I have no means of upgrading to check
whether 

this is a fixed issue. I can't see anything similar in the bug
database.



An expression of the form 

  isset($obj->m['a']['b'])

produces a runtime error when m is not actually an array but a zero
length 

string:

  Uninitialized string offset: 0

The same is the case if I use empty instead of isset.

The same code worked in 5.2. Changing it to 

  isset($obj->m['a']) && isset($obj->m['a']['b'])

works.



isset is not supposed to produce any runtime error, surely, in this kind
of use.



The object member values arise from a database lookup, and normally the
field (m 

above) will be a serialized array in the database, but the first time
the 

database column will be empty, leading to an empty string assignment to
m. In 

addition once populated the object is stored in $_SESSION (actually in 

$_SESSION['p']['q']) and then $obj is obtained by assignment from the
session, 

like this

  $session =& $_SESSION['p']; // where $_SESSION['p'] is set in a
previous page

  // populate new $obj1 from database

  $session['q'] = $obj1;

  ...

  $obj =& $session['q'];

and the offending code is then executed elsewhere some time later.



However, abstracting the code from this much bigger program does not
demonstrate 

the problem, which suggests to me something is corrupted somewhere. This
is what 

I tried on its own, which is as close as I can reasonably get to the
situation 

here, but it works. (The =& are leftovers from what was originally a
PHP4 app; I 

know all objects are assigned by reference in PHP5).



class c { var $m; }



session_start();

if (! isset($_SESSION['p'])) {

  $_SESSION['p'] = array();

  echo "set session array";

  exit;

}

$session =& $_SESSION['p'];

$obj1 = new c();

$obj1->m = '';

$session['q'] = $obj1;

$obj =& $session['q'];

function check() {

  global $obj;

  echo (isset($obj->m['a']['b']) ? 'Yes' : 'No');

}

check();

Expected result:
----------------
isset to return FALSE

Actual result:
--------------
runtime error

Uninitialized string offset: 0


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



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

Reply via email to