As per bug #34199 and as Rob points out, if($obj) and if(!$obj) are
handled by different opcodes and these two opcodes are inconsistent in
whether they call an object's cast_object handler.
if($obj) results in a ZEND_JMPZ_SPEC_CV_HANDLER which calls
i_zend_is_true() which always return true for objects, no matter what
(ignore compatibility mode here) because of this code in zend_execute.h:
case IS_OBJECT:
if(IS_ZEND_STD_OBJECT(*op)) {
TSRMLS_FETCH();
if(EG(ze1_compatibility_mode)) {
result = (zend_hash_num_elements(Z_OBJPROP_P(op))?1:0);
} else {
result = 1;
}
} else {
result = 1;
}
break;
if(!$obj) results in a which calls convert_to_boolean() which in turn
calls convert_object_to_type() which has:
if (Z_OBJ_HT_P(op)->cast_object) {
if (Z_OBJ_HT_P(op)->cast_object(op, op, ctype, 1 TSRMLS_CC) ==
SUCCESS) {
op->type = ctype;
}
This means that any object which actually implements a cast_object
handler that returns false under some condition will be broken. The
simple example is:
$a = simplexml_load_string('<a></a>');
if($a && !$a) echo "BUG!";
I think we need to fix i_zend_is_true's IS_OBJECT case to check to see
if the object has a cast_object handler and call it or just call
convert_to_boolean() there. Or we need to clean this up and not have
such different codepaths for these two cases.
-Rasmus
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php