php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #38122 Misleading error message for recursive use of __get()
Submitted: 2006-07-17 08:14 UTC Modified: 2013-10-28 20:06 UTC
From: toomuchphp-phpbugs at yahoo dot com Assigned:
Status: Not a bug Package: *General Issues
PHP Version: 5.2.0RC1 OS:
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: toomuchphp-phpbugs at yahoo dot com
New email:
PHP Version: OS:

 

 [2006-07-17 08:14 UTC] toomuchphp-phpbugs at yahoo dot com
Description:
------------
Recursive use of __get() results in the misleading error message "Notice: Undefined property:  someClass::$foo in file.php".  It appears at first as though __get() is not being called for some properties and there is no apparent reason why, when the problem is really accidental recursion. PHP correctly detects the recursion and aborts __get(), but the error gives no indication of the recursion problem and it can be very difficult to figure out why __get() is not being called.

I can provide a fix for zend_object_handlers.c, but it really is just a 60-second change to capture the recursiveness error and output an alternative error message.


Reproduce code:
---------------
class test {
    function __get($var) {
        return $this->$var;
    }
}

$obj = new test;
echo $obj->foo;

Expected result:
----------------
Warning: Recursive use of __get() while accessing test::$foo; cannot read property recursive::$foo in <file> on line x

Actual result:
--------------
Notice: Undefined property:  test::$foo in <file> on line x

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2006-08-02 05:02 UTC] toomuchphp-phpbugs at yahoo dot com
Also occurs in PHP-5.2.0RC1.
 [2006-08-15 02:19 UTC] toomuchphp-phpbugs at yahoo dot com
Apologies for the slightly messed-up examples in previous comments.  This is the patch that works for me against 5.2.0RC1.

--- zend_object_handlers.c.original	Tue Aug 15 11:41:38 2006
+++ zend_object_handlers.c	Tue Aug 15 11:45:08 2006
@@ -325,28 +325,36 @@
 		zend_guard *guard;

 		if (zobj->ce->__get &&
-		    zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS &&
-		    !guard->in_get) {
-			/* have getter - try with it! */
-			guard->in_get = 1; /* prevent circular getting */
-			rv = zend_std_call_getter(object, member TSRMLS_CC);
-			guard->in_get = 0;
+		    zend_get_property_guard(zobj, property_info, member, &guard) == SUCCESS) {
+			/* don't allow recursively calling __get() */
+			if(!guard->in_get) {
+				/* have getter - try with it! */
+				guard->in_get = 1; /* prevent circular getting */
+				rv = zend_std_call_getter(object, member TSRMLS_CC);
+				guard->in_get = 0;

-			if (rv) {
-				retval = &rv;
-				if ((type == BP_VAR_W || type == BP_VAR_RW  || type == BP_VAR_UNSET) && rv->refcount > 0) {
-					zval *tmp = rv;
+				if (rv) {
+					retval = &rv;
+					if ((type == BP_VAR_W || type == BP_VAR_RW  || type == BP_VAR_UNSET) && rv->refcount > 0) {
+						zval *tmp = rv;

-					ALLOC_ZVAL(rv);
-					*rv = *tmp;
-					zval_copy_ctor(rv);
-					rv->is_ref = 0;
-					rv->refcount = 0;
-					if (Z_TYPE_P(rv) != IS_OBJECT) {
-						zend_error(E_NOTICE, "Indirect modification of overloaded property %s::$%s has no effect", zobj->ce->name, Z_STRVAL_P(member));
+						ALLOC_ZVAL(rv);
+						*rv = *tmp;
+						zval_copy_ctor(rv);
+						rv->is_ref = 0;
+						rv->refcount = 0;
+						if (Z_TYPE_P(rv) != IS_OBJECT) {
+							zend_error(E_NOTICE, "Indirect modification of overloaded property %s::$%s has no effect", zobj->ce->name, Z_STRVAL_P(member));
+						}
 					}
+				} else {
+					retval = &EG(uninitialized_zval_ptr);
+				}
+			}
+			else {
+				if (!silent) {
+					zend_error(E_WARNING,"Recursive use of __get() trying to read property:  %s::$%s", zobj->ce->name, Z_STRVAL_P(member));
 				}
-			} else {
 				retval = &EG(uninitialized_zval_ptr);
 			}
 		} else {
 [2012-11-19 15:42 UTC] francescrosasbosque at gmail dot com
It still occurs in 5.4.7

Also, why triggering a warning? Why not make it behave just like any other 
function?

class Test {
    function get() {
        return $this->get();
    }
}

(new Test)->get();

# Output

PHP Fatal error:  Maximum function nesting level of '100' reached, aborting! in 
/private/tmp/foo.php on line 5
PHP Stack trace:
PHP   1. {main}() /private/tmp/foo.php:0
PHP   2. Test->get() /private/tmp/foo.php:9
PHP   3. Test->get() /private/tmp/foo.php:5
PHP   4. Test->get() /private/tmp/foo.php:5
...
 [2013-10-28 20:06 UTC] krakjoe@php.net
-Status: Open +Status: Not a bug -Package: Feature/Change Request +Package: *General Issues
 [2013-10-28 20:06 UTC] krakjoe@php.net
This is a baffling request.

I cannot make sense out of what you are asking for, it would appear as though test::$foo is actually undefined; Zend detects recursion correctly and does everything it is supposed to do, so far as I can see it would not be useful or practical to do anything else.

I don't like to, but I'm going to assume that the request came from some misunderstanding rather than some genuine need for change, I genuinely don't understand what you expect is a viable alternative ... if I'm wrong please file a new bug report and I apologize for the inconvenience, just trying to clean up :)
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sun May 11 18:01:27 2025 UTC