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