Hello internals,
Bug #37667 describes a problem with returning an array from __get()
in write context.
<?php
class Class1 {
var $property = array();
function getProperty() {
return $this->property;
}
}
$c = new Class1();
$d = & $c->getProperty();
$d[] = 1;
var_dump($c);
?>
The engine sees the read to the array property as a write no matter
whether it is a read or write operation. I think we should pass the
correct mode and then in the get_property handler use the info to
protect against writing to a returned array since reading it is pretty
fine of course. Right now we use the access type only to silence
warnings in case of BP_VAR_IS. No further distincion is done using
the access type. So i patched the necessary changes into my HEAD and
also verified that the patch does not affect any test case. So it
seems quite good. But i do not want to decide here since it is a) a
change of behavior and b) it introduces a new error message.
Now with the patch applied the above code will result in the following
error message:
Fatal error: Cannot use array returned from Test::__get('property') in write
context in %sbug37667.php on line %d
Comments?
Best regards,
Marcus
Index: Zend/zend_execute.c
===================================================================
RCS file: /repository/ZendEngine2/zend_execute.c,v
retrieving revision 1.746
diff -u -p -d -r1.746 zend_execute.c
--- Zend/zend_execute.c 1 Jun 2006 11:56:23 -0000 1.746
+++ Zend/zend_execute.c 2 Jun 2006 23:05:45 -0000
@@ -1272,7 +1272,7 @@ static void zend_fetch_property_address(
zval *ptr;
if (Z_OBJ_HT_P(container)->read_property &&
- (ptr =
Z_OBJ_HT_P(container)->read_property(container, prop_ptr, BP_VAR_W TSRMLS_CC))
!= NULL) {
+ (ptr =
Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC)) !=
NULL) {
if (result) {
result->var.ptr = ptr;
result->var.ptr_ptr = &result->var.ptr;
@@ -1285,7 +1285,7 @@ static void zend_fetch_property_address(
}
} else if (Z_OBJ_HT_P(container)->read_property) {
if (result) {
- result->var.ptr =
Z_OBJ_HT_P(container)->read_property(container, prop_ptr, BP_VAR_W TSRMLS_CC);
+ result->var.ptr =
Z_OBJ_HT_P(container)->read_property(container, prop_ptr, type TSRMLS_CC);
result->var.ptr_ptr = &result->var.ptr;
}
} else {
Index: Zend/zend_object_handlers.c
===================================================================
RCS file: /repository/ZendEngine2/zend_object_handlers.c,v
retrieving revision 1.167
diff -u -p -d -r1.167 zend_object_handlers.c
--- Zend/zend_object_handlers.c 29 May 2006 19:57:43 -0000 1.167
+++ Zend/zend_object_handlers.c 2 Jun 2006 23:05:46 -0000
@@ -357,6 +357,9 @@ zval *zend_std_read_property(zval *objec
zval_ptr_dtor(&tmp_member);
(*retval)->refcount--;
}
+ if (*retval && (type == BP_VAR_W || type == BP_VAR_RW) &&
Z_TYPE_PP(retval) == IS_ARRAY) {
+ zend_error(E_ERROR, "Cannot use array returned from
%v::__get('%R') in write context", zobj->ce->name, Z_TYPE_P(member),
Z_STRVAL_P(member));
+ }
return *retval;
}
Index: Zend/tests/bug37667.phpt
===================================================================
RCS file: Zend/tests/bug37667.phpt
diff -N Zend/tests/bug37667.phpt
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Zend/tests/bug37667.phpt 2 Jun 2006 23:05:46 -0000
@@ -0,0 +1,57 @@
+--TEST--
+#37667 (Object is not added into array returned by __get)
+--FILE--
+<?php
+
+class Test
+{
+ protected $property = array('foo' => 'bar');
+
+ function __get($name)
+ {
+ return $this->property;
+ }
+}
+
+$obj = new Test;
+
+var_dump($obj->property['foo']);
+var_dump($obj->property[2]);
+
+var_dump($obj);
+
+$obj->property[] = 1;
+$obj->property[] = 2;
+
+var_dump($obj);
+
+?>
+===DONE===
+--EXPECTF--
+string(3) "bar"
+
+Notice: Undefined offset: 2 in %sbug37667.php on line %d
+NULL
+object(Test)#%d (1) {
+ ["property":protected]=>
+ array(1) {
+ ["foo"]=>
+ string(3) "bar"
+ }
+}
+
+Fatal error: Cannot use array returned from Test::__get('property') in write
context in %sbug37667.php on line %d
+--UEXPECTF--
+unicode(3) "bar"
+
+Notice: Undefined offset: 2 in %sbug37667.php on line %d
+NULL
+object(Test)#%d (1) {
+ [u"property":protected]=>
+ array(1) {
+ [u"foo"]=>
+ unicode(3) "bar"
+ }
+}
+
+Fatal error: Cannot use array returned from Test::__get('property') in write
context in %sbug37667.php on line %d
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php