php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #67807 Object passed by reference becomes a string
Submitted: 2014-08-08 15:11 UTC Modified: 2016-07-24 04:22 UTC
From: atlantisnova at gmail dot com Assigned:
Status: No Feedback Package: Scripting Engine problem
PHP Version: 5.4.4 OS: Debian Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: atlantisnova at gmail dot com
New email:
PHP Version: OS:

 

 [2014-08-08 15:11 UTC] atlantisnova at gmail dot com
Description:
------------
My version is PHP 5.4.4-14+deb7u7... Also affects PHP 5.4.4-14+deb7u11 - the production server we discovered it on.

It seems that any sort of notice in a function into which an object has been passed by reference replaces the reference with a string containing its class name.

Code executed after the pass-by-reference also receives the string rather than the original object.

Thanks!

Test script:
---------------
class A{
	function do_stuff(&$b) {
		$defined = 0;
		#trigger_error("If I fixed the undefined variable but enabled this line instead, it will also turn b from an object into a string! So user-triggered notices bork it as well.");
		$x = $undefined || $defined ? 14 : 0;
		var_dump('In function:', $b);
	}
}

class B{}

$a = new A();
$b = new B();

$a->do_stuff($b);

var_dump('After function:', $b);

Expected result:
----------------
$b should be an object of class B

Actual result:
--------------
$b is the string 'B'

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-08-08 17:18 UTC] requinix@php.net
-Status: Open +Status: Feedback -PHP Version: Irrelevant +PHP Version: 5.4.4
 [2014-08-08 17:18 UTC] requinix@php.net
http://3v4l.org/VqsdQ Works for me.

That's the exact repro script you used? And rather than some description of the actual result, how about posting the actual, actual result?
 [2014-08-08 17:22 UTC] atlantisnova at gmail dot com
Yes it's exact and sure here's the output:

( ! ) Notice: Undefined variable: undefined in /vagrant/src/temp.tmp.php on line 6
Call Stack
#	Time	Memory	Function	Location
1	0.0631	4382248	{main}( )	../temp.tmp.php:0
2	0.0631	4385384	A->do_stuff( )	../temp.tmp.php:16
 string 'In function:' (length=12)
string 'B' (length=1)
string 'After function:' (length=15)
string 'B' (length=1)
 [2014-08-08 17:28 UTC] atlantisnova at gmail dot com
More info: my system is a virtualized debian 64 bit machine running on a Mac,,, the production server where we discovered the problem is an dedicated debian 64 box (php versions listed in original comment).

Sorry for not posting the exact output before!

Here's a modified script that shows the correct value of $b before the notice:

class A{
	function do_stuff(&$b) {
		var_dump('Before in function:', $b);
		$defined = 0;
		#trigger_error("If I fixed the undefined variable but enabled this line instead, it will also turn b from an object into a string! So user-triggered notices bork it as well.");
		$x = $undefined || $defined ? 14 : 0;
		var_dump('After in function:', $b);
	}
}

class B{}

$a = new A();
$b = new B();

$a->do_stuff($b);

var_dump('After function:', $b);


---------------  output of above ------------------

string 'Before in function:' (length=19)
object(B)[10]

( ! ) Notice: Undefined variable: undefined in /vagrant/src/temp.tmp.php on line 7
Call Stack
#	Time	Memory	Function	Location
1	0.1017	4382640	{main}( )	../temp.tmp.php:0
2	0.1018	4385776	A->do_stuff( )	../temp.tmp.php:17
 string 'After in function:' (length=18)
string 'B' (length=1)
string 'After function:' (length=15)
string 'B' (length=1)
 [2014-08-08 17:31 UTC] requinix@php.net
What about with Xdebug disabled?
 [2014-08-08 17:45 UTC] aharvey@php.net
I can't reproduce this at all in a Debian Stable x86-64 VM with either the Debian package or a stock 5.4.4 install (tested both with and without xdebug).

Can you provide the full list of modules enabled (php -m), please?
 [2014-08-08 18:04 UTC] atlantisnova at gmail dot com
-Status: Feedback +Status: Open
 [2014-08-08 18:04 UTC] atlantisnova at gmail dot com
Sure here you go:

[PHP Modules]
bcmath
bz2
calendar
Core
ctype
curl
date
dba
dom
ereg
exif
fileinfo
filter
ftp
gd
gettext
hash
iconv
imap
json
libxml
mbstring
mcrypt
memcache
mhash
mysql
mysqli
newrelic
openssl
pcntl
pcre
PDO
pdo_mysql
Phar
posix
Reflection
session
shmop
SimpleXML
soap
sockets
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
wddx
xdebug
xml
xmlreader
xmlwriter
zip
zlib

[Zend Modules]
Xdebug


I also tried xdebug_disable(); but the issue was still there.  Thanks for looking into this!  I'll try disabling xdebug in php.ini and restarting apache next...
 [2014-08-08 18:10 UTC] atlantisnova at gmail dot com
Tried disabling xdebug and newrelic extensions... still no dice.

If there's a private way to submit my phpinfo() I'd be happy to do that.

Thanks!
 [2014-08-08 18:28 UTC] requinix@php.net
-Status: Open +Status: Feedback
 [2014-08-08 18:28 UTC] requinix@php.net
You wouldn't happen to be using a custom error handler, right? If you are, what's the code?
 [2014-08-08 20:06 UTC] atlantisnova at gmail dot com
Why yes, yes I am... sorry it's done in an auto_prepend and I forgot about it.  And yes, that was the problem:

http://3v4l.org/FUqWS (includes the original comment explaining why we were converting to classname)

Looks like the objects returned by debug_backtrace() are true references, and hence when we were looping through to truncate the log message the object got wiped.

So I'm happy because it's an easy fix - feel free to close this ticket unless you feel that debug_backtrace should return object identifiers rather than aliases... looks like it already functions that way in hhvm.

Either way, thanks so much for your time!
 [2014-08-08 20:50 UTC] requinix@php.net
-Status: Feedback +Status: Open -Package: Class/Object related +Package: Scripting Engine problem
 [2014-08-08 20:50 UTC] requinix@php.net
Yeah, that certainly explains it.

So what to do with this? The most similar report I can find is bug #48847 where @stas says that modifying data in the backtrace is "definitely not a supported functionality", but I'm not sure whether to interpret that as meaning undesired behavior (a bug) or undefined behavior (not a bug).
 [2014-08-08 22:01 UTC] atlantisnova at gmail dot com
In case it's helpful for anyone else with similar issues: we discovered this problem because objects seemed to "disappear" between calls, eg:

$my_obj->do_thing1() || $my_obj->do_thing2(); 

$my_obj works fine when do_thing1 is called, but throws a "Call to a member function do_thing2() on a non-object" fatal error on do_thing2.  This is because do_thing1 called an $other_object->other_function($this), which accepted that param by reference (public function other_function(&$obj)).  Any notice (undefined variable, trigger_error, etc) in other_function caused $obj/$this/$my_obj to be rewritten as 'MyClass' due to our custom error handler (which was trying to stringify/truncate the stack trace for logging purposes), and hence the call to do_thing2() failed (since we were calling it on a string).
 [2016-07-14 11:26 UTC] dmitry@php.net
-Status: Open +Status: Feedback
 [2016-07-14 11:26 UTC] dmitry@php.net
I can't reproduce this with PHP-5.3 and above.
 [2016-07-24 04:22 UTC] php-bugs at lists dot php dot net
No feedback was provided. The bug is being suspended because
we assume that you are no longer experiencing the problem.
If this is not the case and you are able to provide the
information that was requested earlier, please do so and
change the status of the bug back to "Re-Opened". Thank you.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Nov 30 00:01:30 2024 UTC