Analysis and Patch for Bug#28491
| From: | Sara Golemon | Date: | Sat, 22 May 2004 21:14:13 +0000 |
| Subject: | Analysis and Patch for Bug#28491 | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-10036@lists.php.net to get a copy of this message | ||
Currently, re-assignment of $this is handled in compile time but that won't
stop anyone from creating a referenc of $this and changing its value. Of
course, any indirect changes to $this won't permanently change the object in
the way that changing $this in PHP4 would have since the value of this isn't
recovered from the symbol table at the end of the method nor will it effect
property/method access since these are handled at compile time.
The end result is the confusion found at http://bugs.php.net/28491
There are three options:
(A) Do nothing, "They shouldn't be trying that anyway!" Obviously that
won't stop someone from attempting it...
(B) Prohibit creating references to $this. Probably "good enough", but
(maybe?) there's a ligitmate use for it.
(C) Check the target variable against $this at execute time. Has the
advantage of keeping the ability to create references of $this but slows
execution, especially when writing to object references from within another
object instance. Note: I didn't compare against EG(This) because the act of
creating a reference to $this separates it from the original zval (which
already has a refcount of greater than 1).
Index: Zend/zend_execute.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute.c,v
retrieving revision 1.645
diff -u -r1.645 zend_execute.c
--- Zend/zend_execute.c 18 May 2004 00:04:22 -0000 1.645
+++ Zend/zend_execute.c 22 May 2004 20:06:55 -0000
@@ -790,6 +790,13 @@
}
}
+ if (EG(This) && (*retval)->type == IS_OBJECT && (*retval)->is_ref
&&
(type == BP_VAR_W || type == BP_VAR_RW)) {
+ /* Make sure the variable we're writing to is not a
reference to $this */
+ zval **thistmp;
+ if (zend_hash_find(EG(active_symbol_table), "this",
sizeof("this"), (void **) &thistmp) == SUCCESS && *retval == *thistmp) {
+ zend_error(E_ERROR, "Cannot re-assign a reference of
$this");
+ }
+ }
if (free_tmp) {
zval_dtor(varname);