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
 [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-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 12:01:31 2024 UTC