Commit:    aa0adce47d9b8ead59efede63a769e395e27bcd5
Author:    Gustavo Lopes <glo...@nebm.ist.utl.pt>         Sat, 19 Jan 2013 
16:21:26 +0100
Parents:   33b104c778c5c0e5446671397aaddd66efa4a7bc
Branches:  PHP-5.3 PHP-5.4 PHP-5.5 master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=aa0adce47d9b8ead59efede63a769e395e27bcd5

Log:
Fix bug #64023 (__toString() & SplFileInfo)

Defining a __toString() method was having no effect when concatenating
the object. This was because the cast_object() handler would ignore
__toString().

Using echo() directly would actually use __toString(), but this was a
bug: the ECHO handler would try zend_std_cast_object_tostring() before
cast_object(), but cast_object() should have priority as
zend_std_cast_object_tostring() assumes an object with a
zend_class_entry.

Bugs:
https://bugs.php.net/64023

Changed paths:
  M  Zend/zend_vm_def.h
  M  Zend/zend_vm_execute.h
  M  ext/spl/spl_directory.c
  A  ext/spl/tests/bug64023.phpt


Diff:
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 3fa5327..e8d3250 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -896,23 +896,12 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMP|VAR|CV, ANY)
 {
        zend_op *opline = EX(opline);
        zend_free_op free_op1;
-       zval z_copy;
        zval *z = GET_OP1_ZVAL_PTR(BP_VAR_R);
 
-       if (OP1_TYPE != IS_CONST &&
-           Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL) {
-           if (OP1_TYPE == IS_TMP_VAR) {
-               INIT_PZVAL(z);
-           }
-               if (zend_std_cast_object_tostring(z, &z_copy, IS_STRING 
TSRMLS_CC) == SUCCESS) {
-                       zend_print_variable(&z_copy);
-                       zval_dtor(&z_copy);
-               } else {
-                       zend_print_variable(z);
-               }
-       } else {
-               zend_print_variable(z);
+       if (OP1_TYPE == IS_TMP_VAR && Z_TYPE_P(z) == IS_OBJECT) {
+               INIT_PZVAL(z);
        }
+       zend_print_variable(z);
 
        FREE_OP1();
        ZEND_VM_NEXT_OPCODE();
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 1ad7f77..f5cedd8 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -1320,23 +1320,12 @@ static int ZEND_FASTCALL  
ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
 
-       zval z_copy;
        zval *z = &opline->op1.u.constant;
 
-       if (IS_CONST != IS_CONST &&
-           Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL) {
-           if (IS_CONST == IS_TMP_VAR) {
-               INIT_PZVAL(z);
-           }
-               if (zend_std_cast_object_tostring(z, &z_copy, IS_STRING 
TSRMLS_CC) == SUCCESS) {
-                       zend_print_variable(&z_copy);
-                       zval_dtor(&z_copy);
-               } else {
-                       zend_print_variable(z);
-               }
-       } else {
-               zend_print_variable(z);
+       if (IS_CONST == IS_TMP_VAR && Z_TYPE_P(z) == IS_OBJECT) {
+               INIT_PZVAL(z);
        }
+       zend_print_variable(z);
 
        ZEND_VM_NEXT_OPCODE();
 }
@@ -4635,23 +4624,12 @@ static int ZEND_FASTCALL  
ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zend_free_op free_op1;
-       zval z_copy;
        zval *z = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
 
-       if (IS_TMP_VAR != IS_CONST &&
-           Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL) {
-           if (IS_TMP_VAR == IS_TMP_VAR) {
-               INIT_PZVAL(z);
-           }
-               if (zend_std_cast_object_tostring(z, &z_copy, IS_STRING 
TSRMLS_CC) == SUCCESS) {
-                       zend_print_variable(&z_copy);
-                       zval_dtor(&z_copy);
-               } else {
-                       zend_print_variable(z);
-               }
-       } else {
-               zend_print_variable(z);
+       if (IS_TMP_VAR == IS_TMP_VAR && Z_TYPE_P(z) == IS_OBJECT) {
+               INIT_PZVAL(z);
        }
+       zend_print_variable(z);
 
        zval_dtor(free_op1.var);
        ZEND_VM_NEXT_OPCODE();
@@ -7898,23 +7876,12 @@ static int ZEND_FASTCALL  
ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
        zend_free_op free_op1;
-       zval z_copy;
        zval *z = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
 
-       if (IS_VAR != IS_CONST &&
-           Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL) {
-           if (IS_VAR == IS_TMP_VAR) {
-               INIT_PZVAL(z);
-           }
-               if (zend_std_cast_object_tostring(z, &z_copy, IS_STRING 
TSRMLS_CC) == SUCCESS) {
-                       zend_print_variable(&z_copy);
-                       zval_dtor(&z_copy);
-               } else {
-                       zend_print_variable(z);
-               }
-       } else {
-               zend_print_variable(z);
+       if (IS_VAR == IS_TMP_VAR && Z_TYPE_P(z) == IS_OBJECT) {
+               INIT_PZVAL(z);
        }
+       zend_print_variable(z);
 
        if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
        ZEND_VM_NEXT_OPCODE();
@@ -21823,23 +21790,12 @@ static int ZEND_FASTCALL  
ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
 
-       zval z_copy;
        zval *z = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
 
-       if (IS_CV != IS_CONST &&
-           Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL) {
-           if (IS_CV == IS_TMP_VAR) {
-               INIT_PZVAL(z);
-           }
-               if (zend_std_cast_object_tostring(z, &z_copy, IS_STRING 
TSRMLS_CC) == SUCCESS) {
-                       zend_print_variable(&z_copy);
-                       zval_dtor(&z_copy);
-               } else {
-                       zend_print_variable(z);
-               }
-       } else {
-               zend_print_variable(z);
+       if (IS_CV == IS_TMP_VAR && Z_TYPE_P(z) == IS_OBJECT) {
+               INIT_PZVAL(z);
        }
+       zend_print_variable(z);
 
        ZEND_VM_NEXT_OPCODE();
 }
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index 0638836..1b6a0e9 100644
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -1873,6 +1873,10 @@ static int spl_filesystem_object_cast(zval *readobj, 
zval *writeobj, int type TS
        spl_filesystem_object *intern = 
(spl_filesystem_object*)zend_object_store_get_object(readobj TSRMLS_CC);
 
        if (type == IS_STRING) {
+               if (Z_OBJCE_P(readobj)->__tostring) {
+                       return std_object_handlers.cast_object(readobj, 
writeobj, type TSRMLS_CC);
+               }
+
                switch (intern->type) {
                case SPL_FS_INFO:
                case SPL_FS_FILE:
diff --git a/ext/spl/tests/bug64023.phpt b/ext/spl/tests/bug64023.phpt
new file mode 100644
index 0000000..2c177f9
--- /dev/null
+++ b/ext/spl/tests/bug64023.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #64023: Overloading __toString() in SplFileInfo has no effect
+--FILE--
+<?php
+class A extends \SplFileInfo
+{
+           public function __toString() {return ' -expected- ';}
+}
+
+$a = new A('/');
+
+// Works
+echo $a, $a->__toString(), $a->__toString() . '', "\n";
+
+// Does not work - outputs parent::__toString()
+echo $a . '', "\n";
+
+--EXPECT--
+ -expected-  -expected-  -expected- 
+ -expected-


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to