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

Reply via email to