Missing __toString() part
| From: | Marcus Boerger | Date: | Sat, 03 Jun 2006 11:42:12 +0000 |
| Subject: | Missing __toString() part | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-23875@lists.php.net to get a copy of this message | ||
Hello guys,
the attached patch closes one more __toString() part. It allows
to use objects that define __toString as indexes to arrays. What do
you guys think about this, should we add it or stay with the old
behavior that didn't allow objects as indexes at all.
--
Best regards,
Marcus mailto:mail@marcus-boerger.de
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 3 Jun 2006 11:37:17 -0000 @@ -919,11 +919,11 @@ static inline HashTable *zend_get_target static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, zval *dim, int type TSRMLS_DC) { - zval **retval; + zval **retval, dim_copy; zstr offset_key; int offset_key_length; zend_uchar ztype = Z_TYPE_P(dim); - int free_offset = 0; + int free_offset = 0, use_copy = 0; switch (ztype) { case IS_NULL: @@ -931,6 +931,15 @@ static inline zval **zend_fetch_dimensio offset_key.s = ""; offset_key_length = 1; goto fetch_string_dim; + + case IS_OBJECT: + zend_make_printable_zval(dim, &dim_copy, &use_copy TSRMLS_CC); + if (use_copy) { + dim = &dim_copy; + } + ztype = Z_TYPE_P(dim); + /* no break */ + case IS_STRING: case IS_UNICODE: @@ -975,6 +984,9 @@ fetch_string_dim: if (free_offset) { efree(offset_key.v); } + if (use_copy) { + zval_dtor(&dim_copy); + } break; case IS_RESOURCE: zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(dim), Z_LVAL_P(dim)); Index: Zend/tests/offset_object_tostring.phpt =================================================================== RCS file: Zend/tests/offset_object_tostring.phpt diff -N Zend/tests/offset_object_tostring.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/offset_object_tostring.phpt 3 Jun 2006 11:37:17 -0000 @@ -0,0 +1,51 @@ +--TEST-- +accessing array dimension via object's __tostring +--FILE-- +<?php + +function my_error_handler($code, $msg) +{ + echo "$msg\n"; +} + +set_error_handler('my_error_handler'); + +class Test +{ + function __toString() + { + return 'foo'; + } +} + +class Fail +{ + function __toString() + { + throw new Exception(__METHOD__); + } +} + +$arr = array(0 => 42, 'foo' => 'bar'); + +var_dump($arr[new Test]); + +var_dump($arr[new stdClass]); + +var_dump($arr[new Fail]); +?> +===DONE=== +--EXPECTF-- +string(3) "bar" +Object of class stdClass could not be converted to string +Undefined index: +NULL + +Fatal error: Method Fail::__toString() must not throw an exception in %soffset_object_tostring.php on line %d +--UEXPECTF-- +unicode(3) "bar" +Object of class stdClass could not be converted to string +Undefined index: +NULL + +Fatal error: Method Fail::__toString() must not throw an exception in %soffset_object_tostring.php on line %d
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 3 Jun 2006 11:37:17 -0000 @@ -919,11 +919,11 @@ static inline HashTable *zend_get_target static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, zval *dim, int type TSRMLS_DC) { - zval **retval; + zval **retval, dim_copy; zstr offset_key; int offset_key_length; zend_uchar ztype = Z_TYPE_P(dim); - int free_offset = 0; + int free_offset = 0, use_copy = 0; switch (ztype) { case IS_NULL: @@ -931,6 +931,15 @@ static inline zval **zend_fetch_dimensio offset_key.s = ""; offset_key_length = 1; goto fetch_string_dim; + + case IS_OBJECT: + zend_make_printable_zval(dim, &dim_copy, &use_copy TSRMLS_CC); + if (use_copy) { + dim = &dim_copy; + } + ztype = Z_TYPE_P(dim); + /* no break */ + case IS_STRING: case IS_UNICODE: @@ -975,6 +984,9 @@ fetch_string_dim: if (free_offset) { efree(offset_key.v); } + if (use_copy) { + zval_dtor(&dim_copy); + } break; case IS_RESOURCE: zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", Z_LVAL_P(dim), Z_LVAL_P(dim)); Index: Zend/tests/offset_object_tostring.phpt =================================================================== RCS file: Zend/tests/offset_object_tostring.phpt diff -N Zend/tests/offset_object_tostring.phpt --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Zend/tests/offset_object_tostring.phpt 3 Jun 2006 11:37:17 -0000 @@ -0,0 +1,51 @@ +--TEST-- +accessing array dimension via object's __tostring +--FILE-- +<?php + +function my_error_handler($code, $msg) +{ + echo "$msg\n"; +} + +set_error_handler('my_error_handler'); + +class Test +{ + function __toString() + { + return 'foo'; + } +} + +class Fail +{ + function __toString() + { + throw new Exception(__METHOD__); + } +} + +$arr = array(0 => 42, 'foo' => 'bar'); + +var_dump($arr[new Test]); + +var_dump($arr[new stdClass]); + +var_dump($arr[new Fail]); +?> +===DONE=== +--EXPECTF-- +string(3) "bar" +Object of class stdClass could not be converted to string +Undefined index: +NULL + +Fatal error: Method Fail::__toString() must not throw an exception in %soffset_object_tostring.php on line %d +--UEXPECTF-- +unicode(3) "bar" +Object of class stdClass could not be converted to string +Undefined index: +NULL + +Fatal error: Method Fail::__toString() must not throw an exception in %soffset_object_tostring.php on line %d