RE: [PHP-DEV] Inconsistency between FETCH_DIM_IS and FETCH_OBJ_IS
| From: | Andi Gutmans | Date: | Thu, 06 Jul 2006 06:14:03 +0000 |
| Subject: | RE: [PHP-DEV] Inconsistency between FETCH_DIM_IS and FETCH_OBJ_IS | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-24281@lists.php.net to get a copy of this message | ||
Looks good to me. Thanks!
> -----Original Message-----
> From: Sara Golemon [mailto:pollita@php.net]
> Sent: Wednesday, July 05, 2006 2:00 PM
> To: internals@lists.php.net
> Subject: [PHP-DEV] Inconsistency between FETCH_DIM_IS and FETCH_OBJ_IS
>
> When executing ZEND_FETCH_OBJ_IS on a non-object, the handler
> dispatches to zend_fetch_property_address_read_helper with
> type==BP_VAR_IS and ends up generating an error (isset() is
> supposed to be quiet) here:
>
> if (Z_TYPE_P(container) != IS_OBJECT ||
> !Z_OBJ_HT_P(container)->read_property) {
> zend_error(E_NOTICE, "Trying to get property of non-object");
> *retval = EG(uninitialized_zval_ptr);
> SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
> AI_USE_PTR(EX_T(opline->result.u.var).var);
>
>
> It's cousin ZEND_FETCH_DIM_IS winds up at
> zend_fetch_dimension_address() where the non-arrayness of op1
> is handled via these case statements:
> case IS_NULL: {
> /* for read-mode only */
> if (result) {
> result->var.ptr_ptr = &EG(uninitialized_zval_ptr);
> PZVAL_LOCK(*result->var.ptr_ptr);
> }
> if (type==BP_VAR_W || type==BP_VAR_RW) {
> zend_error(E_WARNING, "Cannot use a NULL
> value as an array");
> }
> break;
> }
> default: {
> switch (type) {
> case BP_VAR_UNSET:
> zend_error(E_WARNING, "Cannot unset
> offset in a non-array variable");
> /* break missing intentionally */
> case BP_VAR_R:
> case BP_VAR_IS:
> retval = &EG(uninitialized_zval_ptr);
> break;
> default:
> retval = &EG(error_zval_ptr);
> break;
> }
> if (result) {
> result->var.ptr_ptr = retval;
> PZVAL_LOCK(*result->var.ptr_ptr);
> }
> if (type==BP_VAR_W || type==BP_VAR_RW) {
> zend_error(E_WARNING, "Cannot use a
> scalar value as an array");
> }
> }
>
> Which indicate the expected behavior of silent failure. It's
> probably gone undetected till now as it requires fetching a
> property or dimension offset from a property in a third
> (non-object) variable within an isset() statement:
>
> $foo = NULL;
> isset($foo->bar->baz);
>
> Unless someone can suggest why Objects should be noisy inside
> isset(), I'd like to suggest the following fix:
>
> Index: Zend/zend_vm_def.h
> ===================================================================
> RCS file: /repository/ZendEngine2/zend_vm_def.h,v
> retrieving revision 1.120
> diff -u -r1.120 zend_vm_def.h
> --- Zend/zend_vm_def.h 13 Jun 2006 12:56:20 -0000 1.120
> +++ Zend/zend_vm_def.h 5 Jul 2006 20:52:41 -0000
> @@ -1176,7 +1176,9 @@
>
>
> if (Z_TYPE_P(container) != IS_OBJECT ||
> !Z_OBJ_HT_P(container)->read_property) {
> - zend_error(E_NOTICE, "Trying to get property
> of non-object");
> + if (type != BP_VAR_IS) {
> + zend_error(E_NOTICE, "Trying to get
> property of non-object");
> + }
> *retval = EG(uninitialized_zval_ptr);
> SELECTIVE_PZVAL_LOCK(*retval, &opline->result);
> AI_USE_PTR(EX_T(opline->result.u.var).var);
>
>
> I suggest only excluding BP_VAR_IS since the matching
> behavior for unset()/DIM is to throw a notice. I could
> potentially see excluding BP_VAR_R in order to match
> read/DIM, but personally I never liked that behavior :)
>
> -Sara