php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #31525 object reference being dropped. $this getting lost.
Submitted: 2005-01-13 00:49 UTC Modified: 2005-05-05 19:45 UTC
Votes:3
Avg. Score:4.0 ± 0.8
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:0 (0.0%)
From: yml at yml dot com Assigned: andi
Status: Closed Package: Scripting Engine problem
PHP Version: 5CVS-2005-03-03 OS: *
Private report: No CVE-ID:
 [2005-01-13 00:49 UTC] yml at yml dot com
Description:
------------
PHP 5.0.3 using the recommended php.ini with all warnings and errors turned on. RedHat 9. Apache 1.3.33. Config:

./configure  --with-apxs=/usr/local/apache/bin/apxs --with-mysql=/usr/local/mysql --prefix=/usr/local/php_5.0.3 --with-mcrypt=/usr/local/lib --with-gd --with-jpeg-dir=/usr/lib --with-zlib-dir=/usr/lib --with-png-dir=/usr/lib --enable-debug --enable-dmalloc --disable-inline-optimization

This may be related to bug http://bugs.php.net/31508. Under PHP 4.3.10 the section of code in question causes a busy loop. Under PHP 5 it causes an object to be dropped. 

More info, sample code and a sample run can be found at:

http://www.yml.com/homepage.html?COMP=clog_list&cmd=detail&cs_clog_entries_ref=149

I have a test case that is a radically reduced version of a large body of code. fv_baseComponent extends fv_baseWidget which extends fvTree. I create a minimal fv_baseComponent. 

It calls a method in the fv_baseWidget base class called getAttributeValue(). 

getAttributeValue calls getParentControl() which is present in both fv_baseWidget and fv_baseComponent. 

In fv_baseComponent getParentControl just returns "$this".

The returned value is then used to call a method in the fv_baseComponent class.

All this happens in the constructor for fv_baseComponent (which I suspect is the cause of the problem).

Once the getAttributeValue() is called in the fv_baseComponent constructor, '$this' is no longer a valid object. 

If I turn on PHP 4 compatibility mode it seems to work. The code works under PHP 4. (however in the full application the same code seems to have problems under PHP 4.3.10 causing a busy loop).

If you need to contact me from an email address other than bugs@php.net please use the form at

http://www.yml.com/Contact_Yermo.html 

otherwise I will miss your email in all the spam I get.


Reproduce code:
---------------
See the download available at:

http://www.yml.com/homepage.html?COMP=clog_list&cmd=detail&cs_clog_entries_ref=149

It contains base_widget.php, base_component.php, fvTree.php and test.php.

The relevant snippet from test.php contains:

$currentComponent =& new fv_baseComponent( $nullVar, $nullVar, $nullVar, "static", $nullVar );

ddt( "After creating fv_baseComponent - currentComponent type is '" . gettype( $currentComponent ) . "'");

$currentComponent->getAttributeValue( "hello" );

// at this point $this is destroyed. Is "unknown type".

ddt( "after getAttributeValue() call - currentComponent type is '" . gettype( $currentComponent ) . "'" );


// this method call will fail.

$currentComponent->setName( "test" );

ddt( "The end - currentComponent type is '" . gettype( $currentComponent ) . "'");


Expected result:
----------------
PHP should not produce any errors when the above is run.

Actual result:
--------------
test.php:30 - before class includes

test.php:30 - Creating fv_staticCtrl instance

test.php:30 - fv_baseComponent Constructor: Before getAttributeValue() call. Type of 'this' is 'object'

test.php:30 - fv_basewidget::getAttributeValue() - Object id #1 is 'object'

test.php:30 - fv_baseWidget::getAttributeValue() - value 'Hello from varLookupATTRS' - type of parentComponent object is 'object'

test.php:30 - fv_baseComponent Constructor: after getAttributeValue() call. Type of 'this' is 'object'
Warning: Attempt to assign property of non-object in /usr/local2/WWW/mobie.yml.com/mobie/admin_ui/tests/php_5_test/base_component.php on line 125

test.php:30 - After creating fv_baseComponent - currentComponent type is 'object'

test.php:30 - fv_basewidget::getAttributeValue() - Object id #1 is 'object'

test.php:30 - fv_baseWidget::getAttributeValue() - value 'Hello from varLookupATTRS' - type of parentComponent object is 'object'

test.php:30 - after getAttributeValue() call - currentComponent type is 'unknown type'
Fatal error: Call to a member function setName() on a non-object in /usr/local2/WWW/mobie.yml.com/mobie/admin_ui/tests/php_5_test/test.php on line 59

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-01-26 04:32 UTC] sniper@php.net
Thank you for this bug report. To properly diagnose the problem, we
need a short but complete example script to be able to reproduce
this bug ourselves. 

A proper reproducing script starts with <?php and ends with ?>,
is max. 10-20 lines long and does not require any external 
resources such as databases, etc.

If possible, make the script source available online and provide
an URL to it here. Try to avoid embedding huge scripts into the report.


 [2005-01-26 05:17 UTC] yml at yml dot com
Umm. Check the script I put together for you at:

http://www.yml.com/homepage.html?COMP=clog_list&cmd=detail&cs_clog_entries_ref=149

If you have trouble accessing it please let me know.
 [2005-01-26 09:08 UTC] derick@php.net
Just a simple page with the script please, or paste it here.
 [2005-01-27 02:13 UTC] yml at yml dot com
I forgot to mention, check the few lines at the very bottom of the code. Unfortunately the class definitions are required to reproduce the error but the basic script is extremely simple.

Under PHP 5 you get a Warning: Attempt to assign property of non-object in /usr/local2/WWW/mobie.yml.com/mobie/admin_ui/tests/php_5_test/test.php on line 407

Under PHP 4 it runs through the 1000 iterations without fail.

It's very simple code. This code used to run in PHP 5.0, but something changed in later versions to cause this error to crop up.
 [2005-02-28 21:10 UTC] sniper@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5-win32-latest.zip

..and NEVER ever attach such HUGE scripts in your report!!!!

 [2005-03-03 18:32 UTC] yml at yml dot com
1. Same problem. No improvement. $this is getting dropped. Used to work in 5.0RC2. Since 5.0.3 it's been broken. 

2. The script I sent was puny. Given how terribly buggy the Zend engine is, expecting that all serious parser errors can be reproduced in a total of 20 lines or less is ridiculous. The meat of the script I sent clearly reproduces the problem in 8 lines, not including the supporting classes. 

You guys wouldn't pull it from my site; and now you won't look at it if I send it to you. Exactly what would you propose I do to help you track this down?

The 85,000 lines of code that's actually having this problem (and producing a coredump), now that's a huge "script".
 [2005-03-06 01:26 UTC] michaels at crye-leike dot com
FWIW, here's a shorter script that reproduces the problem for me on PHP 5.0.3:

<?php
class Foo {
  function getThis() {
    return $this;
  }
  function destroyThis() {
    $baz =& $this->getThis();
  }
}
$bar = new Foo();
$bar->destroyThis();
var_dump($bar);
?>

This outputs:
NULL

If I change the assign-by-reference operator (=&) to the normal assignment operator (=) inside destroyThis(), I get:
object(Foo)#1 (0) {
}

Hope this helps...
 [2005-03-06 01:50 UTC] yml at yml dot com
Unfortunately the shortened script works as it should if you declare getThis to return a reference  as in 

function &getThis()

If however, you refer to the "too-long" script I put together at:

http://www.formvista.com/uploaded_files/php5_drops_object.php.txt

There is something different about it that causes $this to get dropped even when the method is declared return-by-reference.

I haven't been able to narrow it down but it's entirely possible I'm overlooking something obvious.

It's got to be something related to legacy pass by reference notation =&. The strange thing is it worked in 5.0.1 and broke in 5.0.2 or .3.
 [2005-03-06 02:43 UTC] michaels at crye-leike dot com
True, if getThis() is declared to return a reference then everything works as expected.  However, looking through the original reproduce code I noticed something else.  If you add parentheses around $this in getThis() then the unexpected behavior returns.  Complete code:

<?php
class Foo {
  function &getThis() {
    return ($this);
  }
  function destroyThis() {
    $baz =& $this->getThis();
  }
}
$bar = new Foo();
$bar->destroyThis();
var_dump($bar);
?>

Produces:
NULL

Expected:
object(Foo)#1 (0) {
}
 [2005-03-06 05:55 UTC] yml at yml dot com
Problem found.

Removing all the ()'s from reference returning functions and the problem has completely disappeared.

However, the case should be caught by the parser and a warning generated. Using parens around returns returning references will cause symbol table corruption occassionally ...
 [2005-04-29 03:46 UTC] sniper@php.net
Andi, I think you once responded to similar issue regarding return() with/without parenthesis..



 [2005-05-05 19:45 UTC] dmitry@php.net
Fixed in CVS HEAD and PHP_5_0.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sun Apr 20 13:01:59 2014 UTC