]> granicus.if.org Git - php/commitdiff
Fix SXE->string cast for __toString in inheriting class
authorNikita Popov <nikic@php.net>
Sat, 3 May 2014 08:49:10 +0000 (10:49 +0200)
committerNikita Popov <nikic@php.net>
Sat, 3 May 2014 09:29:08 +0000 (11:29 +0200)
This issue was originally hacked around in zend_make_printable_zval.
I've now moved the overridden __toString() handling into the SXE
cast_object handler, so everything invoking that handler
(zend_make_printable_zval, convert_to_string, zval_get_string,
and various other more obscure usages) see the same behavior.

Zend/zend.c
Zend/zend_operators.c
ext/simplexml/simplexml.c

index f4bab5032c7791219fbbf4a9356ed85464aba758..6706bad59d9567003792682f1b79ab6eec41c105 100644 (file)
@@ -247,9 +247,6 @@ again:
                        {
                                TSRMLS_FETCH();
 
-                               if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING TSRMLS_CC) == SUCCESS) {
-                                       break;
-                               }
                                if (Z_OBJ_HANDLER_P(expr, cast_object)) {
                                        zval val;
 
index 5c79a98142e251961aa2071bedaa44a61367171c..4093a8adea2e39e2873a4b6211787b99ddcc37f5 100644 (file)
@@ -921,9 +921,6 @@ try_again:
                        return STR_INIT("Array", sizeof("Array")-1, 0);
                case IS_OBJECT: {
                        zval tmp;
-                       //???if (zend_std_cast_object_tostring(op, &tmp, IS_STRING TSRMLS_CC) == SUCCESS) {
-                       //???   return Z_STR(tmp);
-                       //???}
                        if (Z_OBJ_HT_P(op)->cast_object) {
                                if (Z_OBJ_HT_P(op)->cast_object(op, &tmp, IS_STRING TSRMLS_CC) == SUCCESS) {
                                        return Z_STR(tmp);
index 9e04b592b7020981da53f2b844fda28672be221a..4ee251ecf84989f207829dc15555bd6d54447054 100644 (file)
@@ -1774,7 +1774,7 @@ static int cast_object(zval *object, int type, char *contents TSRMLS_DC)
 
 /* {{{ sxe_object_cast()
  */
-static int sxe_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
+static int sxe_object_cast_ex(zval *readobj, zval *writeobj, int type TSRMLS_DC)
 {
        php_sxe_object *sxe;
        xmlChar        *contents = NULL;
@@ -1826,13 +1826,25 @@ static int sxe_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
 }
 /* }}} */
 
+/* Variant of sxe_object_cast_ex that handles overwritten __toString() method */
+static int sxe_object_cast(zval *readobj, zval *writeobj, int type TSRMLS_DC)
+{
+       if (type == IS_STRING
+               && zend_std_cast_object_tostring(readobj, writeobj, IS_STRING TSRMLS_CC) == SUCCESS
+       ) {
+               return SUCCESS;
+       }
+
+       return sxe_object_cast_ex(readobj, writeobj, type TSRMLS_CC);
+}
+
 /* {{{ proto object SimpleXMLElement::__toString() U
    Returns the string content */
 SXE_METHOD(__toString)
 {
        zval           result;
 
-       if (sxe_object_cast(getThis(), &result, IS_STRING TSRMLS_CC) == SUCCESS) {
+       if (sxe_object_cast_ex(getThis(), &result, IS_STRING TSRMLS_CC) == SUCCESS) {
                RETURN_ZVAL(&result, 0, 0);
        } else {
                zval_ptr_dtor(&result);
@@ -1909,7 +1921,7 @@ SXE_METHOD(count)
 
 static zval *sxe_get_value(zval *z, zval *rv TSRMLS_DC) /* {{{ */
 {
-       if (sxe_object_cast(z, rv, IS_STRING TSRMLS_CC) == FAILURE) {
+       if (sxe_object_cast_ex(z, rv, IS_STRING TSRMLS_CC) == FAILURE) {
                zend_error(E_ERROR, "Unable to cast node to string");
                /* FIXME: Should not be fatal */
        }