From f94344d7fdc816372e4548bbcec429a8ebc12d0c Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 27 Sep 2005 07:59:18 +0000 Subject: [PATCH] Changed __toString() behavior to call it in all necessary places --- NEWS | 2 + Zend/tests/bug26166.phpt | 2 +- Zend/zend.c | 117 ++++++++--------------- Zend/zend.h | 1 + Zend/zend_API.c | 14 ++- Zend/zend_API.h | 1 + Zend/zend_compile.c | 6 ++ Zend/zend_compile.h | 1 + Zend/zend_object_handlers.c | 41 ++++---- Zend/zend_vm_def.h | 46 ++++----- Zend/zend_vm_execute.h | 184 ++++++++++++++++-------------------- tests/classes/tostring.phpt | 74 +++++++++++---- 12 files changed, 237 insertions(+), 252 deletions(-) diff --git a/NEWS b/NEWS index 0fb04e3cac..3e5d89bedd 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,8 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 6.0 - Unicode support. (Andrei, Dmitriy, et al) +- Changed __toString() behavior to call it in all necessary places + (Marcus, Dmitry) - Changed "instanceof" and "catch" operators, is_a() and is_subclass_of() functions to not call __autoload(). (Dmitry) - cURL improvements: (Ilia) diff --git a/Zend/tests/bug26166.phpt b/Zend/tests/bug26166.phpt index 1c3934ac91..e2800ad878 100755 --- a/Zend/tests/bug26166.phpt +++ b/Zend/tests/bug26166.phpt @@ -64,4 +64,4 @@ Hello World! Got the exception ===NONE=== -Fatal error: Method None::__toString() must return a string value in %sbug26166.php on line %d +Catchable fatal error: Method None::__toString() must return a string value in %sbug26166.php on line %d diff --git a/Zend/zend.c b/Zend/zend.c index 8de73997a1..37108066ac 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -347,39 +347,28 @@ ZEND_API void zend_make_string_zval(zval *expr, zval *expr_copy, int *use_copy) case IS_OBJECT: { TSRMLS_FETCH(); -#if 0 - /* Standard PHP objects */ - if (Z_OBJ_HT_P(expr) == &std_object_handlers || !Z_OBJ_HT_P(expr)->cast_object) { - if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) { - break; - } - zend_error(E_NOTICE, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name); - } -#endif if (Z_OBJ_HANDLER_P(expr, cast_object)) { if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) { break; } - } else { - if(Z_OBJ_HANDLER_P(expr, get)) { - zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC); - if(Z_TYPE_P(z) != IS_OBJECT) { - zend_make_printable_zval(z, expr_copy, use_copy); - FREE_ZVAL(z); - return; - } + } + if (Z_OBJ_HANDLER_P(expr, get)) { + zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC); + if(Z_TYPE_P(z) != IS_OBJECT) { + zend_make_printable_zval(z, expr_copy, use_copy); + FREE_ZVAL(z); + break; } } if (EG(exception)) { - zval_dtor(expr_copy); expr_copy->value.str.len = 0; expr_copy->value.str.val = STR_EMPTY_ALLOC(); break; } + } expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG); expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle); - expr_copy->type = IS_STRING; break; default: *expr_copy = *expr; @@ -387,6 +376,7 @@ ZEND_API void zend_make_string_zval(zval *expr, zval *expr_copy, int *use_copy) convert_to_string(expr_copy); break; } + expr_copy->type = IS_STRING; *use_copy = 1; } @@ -426,40 +416,26 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop expr_copy->value.str.val = estrndup("Array", expr_copy->value.str.len); break; case IS_OBJECT: - { -#if 0 - /* Standard PHP objects */ - if (Z_OBJ_HT_P(expr) == &std_object_handlers || !Z_OBJ_HT_P(expr)->cast_object) { - if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) { - break; - } - zend_error(E_NOTICE, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name); - } -#endif - if (Z_OBJ_HANDLER_P(expr, cast_object)) { - if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) { - break; - } - } else { - if(Z_OBJ_HANDLER_P(expr, get)) { - zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC); - if(Z_TYPE_P(z) != IS_OBJECT) { - zend_make_printable_zval(z, expr_copy, use_copy); - FREE_ZVAL(z); - return; - } - } + if (Z_OBJ_HANDLER_P(expr, cast_object)) { + if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) { + break; } - if (EG(exception)) { - zval_dtor(expr_copy); - expr_copy->value.str.len = 0; - expr_copy->value.str.val = STR_EMPTY_ALLOC(); + } + if (Z_OBJ_HANDLER_P(expr, get)) { + zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC); + if(Z_TYPE_P(z) != IS_OBJECT) { + zend_make_printable_zval(z, expr_copy, use_copy); + FREE_ZVAL(z); break; } } + if (EG(exception)) { + expr_copy->value.str.len = 0; + expr_copy->value.str.val = STR_EMPTY_ALLOC(); + break; + } expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG); expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle); - expr_copy->type = IS_STRING; break; case IS_DOUBLE: *expr_copy = *expr; @@ -491,40 +467,26 @@ ZEND_API void zend_make_unicode_zval(zval *expr, zval *expr_copy, int *use_copy) } switch (expr->type) { case IS_OBJECT: - { -#if 0 - /* Standard PHP objects */ - if (Z_OBJ_HT_P(expr) == &std_object_handlers || !Z_OBJ_HT_P(expr)->cast_object) { - if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) { - break; - } - zend_error(E_NOTICE, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name); - } -#endif - if (Z_OBJ_HANDLER_P(expr, cast_object)) { - if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_UNICODE, 0 TSRMLS_CC) == SUCCESS) { - break; - } - } else { - if(Z_OBJ_HANDLER_P(expr, get)) { - zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC); - if(Z_TYPE_P(z) != IS_OBJECT) { - zend_make_unicode_zval(z, expr_copy, use_copy); - FREE_ZVAL(z); - return; - } - } + if (Z_OBJ_HANDLER_P(expr, cast_object)) { + if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_UNICODE, 0 TSRMLS_CC) == SUCCESS) { + break; } - if (EG(exception)) { - zval_dtor(expr_copy); - expr_copy->value.ustr.len = 0; - expr_copy->value.ustr.val = USTR_MAKE(""); + } + if (Z_OBJ_HANDLER_P(expr, get)) { + zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC); + if(Z_TYPE_P(z) != IS_OBJECT) { + zend_make_unicode_zval(z, expr_copy, use_copy); + FREE_ZVAL(z); break; } } - expr_copy->value.ustr.val = emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG + 1); + if (EG(exception)) { + expr_copy->value.ustr.len = 0; + expr_copy->value.ustr.val = USTR_MAKE(""); + break; + } + expr_copy->value.ustr.val = eumalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG + 1); expr_copy->value.ustr.len = u_sprintf(expr_copy->value.ustr.val, "Object id #%ld", (long)expr->value.obj.handle); - expr_copy->type = IS_UNICODE; break; default: *expr_copy = *expr; @@ -532,6 +494,7 @@ ZEND_API void zend_make_unicode_zval(zval *expr, zval *expr_copy, int *use_copy) convert_to_unicode(expr_copy); break; } + expr_copy->type = IS_UNICODE; *use_copy = 1; } @@ -969,6 +932,8 @@ static void fix_classes(HashTable *ht) { ce->__isset = ce->__isset->common.u_twin; } else if (ce->__call) { ce->__call = ce->__call->common.u_twin; + } else if (ce->__tostring) { + ce->__tostring = ce->__tostring->common.u_twin; } else if (ce->serialize_func) { ce->serialize_func = ce->serialize_func->common.u_twin; } else if (ce->unserialize_func) { diff --git a/Zend/zend.h b/Zend/zend.h index 2590398467..53e3d05705 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -360,6 +360,7 @@ struct _zend_class_entry { union _zend_function *__unset; union _zend_function *__isset; union _zend_function *__call; + union _zend_function *__tostring; union _zend_function *serialize_func; union _zend_function *unserialize_func; diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 7fd4ba8496..22d43f5226 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2022,6 +2022,9 @@ ZEND_API void zend_check_magic_method_implementation(zend_class_entry *ce, zend_ } else if (lcname_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1) && fptr->common.num_args != 2) { zend_error(error_type, "Method %v::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME); + } else if (lcname_len == sizeof(ZEND_TOSTRING_FUNC_NAME) - 1 && + ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && fptr->common.num_args != 0) { + zend_error(error_type, "Method %v::%s() cannot take arguments", ce->name, ZEND_CALL_FUNC_NAME); } efree(lcname); } @@ -2035,7 +2038,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr int count=0, unload=0; HashTable *target_function_table = function_table; int error_type; - zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL; + zend_function *ctor = NULL, *dtor = NULL, *clone = NULL, *__get = NULL, *__set = NULL, *__unset = NULL, *__isset = NULL, *__call = NULL, *__tostring = NULL; char *lowercase_name; int fname_len; char *lc_class_name; @@ -2139,6 +2142,8 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr clone = reg_function; } else if ((fname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) { __call = reg_function; + } else if ((fname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME))) { + __tostring = reg_function; } else if ((fname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) { __get = reg_function; } else if ((fname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && !memcmp(lowercase_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) { @@ -2176,6 +2181,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr scope->destructor = dtor; scope->clone = clone; scope->__call = __call; + scope->__tostring = __tostring; scope->__get = __get; scope->__set = __set; scope->__unset = __unset; @@ -2207,6 +2213,12 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr } __call->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; } + if (__tostring) { + if (__tostring->common.fn_flags & ZEND_ACC_STATIC) { + zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __tostring->common.function_name); + } + __tostring->common.fn_flags &= ~ZEND_ACC_ALLOW_STATIC; + } if (__get) { if (__get->common.fn_flags & ZEND_ACC_STATIC) { zend_error(error_type, "Method %s::%s() cannot be static", scope->name, __get->common.function_name); diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 8c21671dc9..5720878166 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -131,6 +131,7 @@ typedef struct _zend_function_entry { class_container.create_object = NULL; \ class_container.interface_gets_implemented = NULL; \ class_container.__call = handle_fcall; \ + class_container.__tostring = NULL; \ class_container.__get = handle_propget; \ class_container.__set = handle_propset; \ class_container.__unset = handle_propunset; \ diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 1a8c66fb71..2a19b0398f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1163,6 +1163,8 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array); } else if ((lcname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) { CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array); + } else if ((lcname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) { + CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array); } else if (!(fn_flags & ZEND_ACC_STATIC)) { CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC; } @@ -1873,6 +1875,9 @@ static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC) if (!ce->__call) { ce->__call = ce->parent->__call; } + if (!ce->__tostring) { + ce->__tostring = ce->parent->__tostring; + } if (!ce->clone) { ce->clone = ce->parent->clone; } @@ -4152,6 +4157,7 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify ce->__unset = NULL; ce->__isset = NULL; ce->__call = NULL; + ce->__tostring = NULL; ce->create_object = NULL; ce->get_iterator = NULL; ce->iterator_funcs.funcs = NULL; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 6fd22cbd6a..a8d56e917b 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -723,6 +723,7 @@ END_EXTERN_C() #define ZEND_UNSET_FUNC_NAME "__unset" #define ZEND_ISSET_FUNC_NAME "__isset" #define ZEND_CALL_FUNC_NAME "__call" +#define ZEND_TOSTRING_FUNC_NAME "__tostring" #define ZEND_AUTOLOAD_FUNC_NAME "__autoload" #endif /* ZEND_COMPILE_H */ diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index bf8fec3c20..de0d27213d 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1008,37 +1008,30 @@ int zend_std_object_get_class_name(zval *object, char **class_name, zend_uint *c ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC) { - zval fname, *retval; + zval *retval; + zend_class_entry *ce; switch (type) { case IS_STRING: case IS_UNICODE: - if (!zend_hash_exists(&Z_OBJCE_P(readobj)->function_table, "__tostring", sizeof("__tostring"))) { - return FAILURE; - } - ZVAL_ASCII_STRING(&fname, "__tostring", 0); - if (call_user_function_ex(NULL, &readobj, &fname, &retval, 0, NULL, 0, NULL TSRMLS_CC) == SUCCESS) { - if (UG(unicode)) { - zval_dtor(&fname); - } - if (retval) { - if (Z_TYPE_P(retval) != (UG(unicode)?IS_UNICODE:IS_STRING)) { - zend_error(E_ERROR, "Method %v::__toString() must return a string value", Z_OBJCE_P(readobj)->name); + ce = Z_OBJCE_P(readobj); + if (ce->__tostring && + zend_call_method_with_0_params(&readobj, ce, &ce->__tostring, "__tostring", &retval)) { + if (Z_TYPE_P(retval) == (UG(unicode)?IS_UNICODE:IS_STRING)) { + *writeobj = *retval; + zval_copy_ctor(writeobj); + zval_ptr_dtor(&retval); + INIT_PZVAL(writeobj); + if (Z_TYPE_P(writeobj) != type) { + convert_to_explicit_type(writeobj, type); } + return SUCCESS; } else { - MAKE_STD_ZVAL(retval); - ZVAL_ASCII_STRINGL(retval, "", 0, 1); + zval_ptr_dtor(&retval); + zend_error(E_RECOVERABLE_ERROR, "Method %v::__toString() must return a string value", ce->name); } - *writeobj = *retval; - zval_copy_ctor(writeobj); - INIT_PZVAL(writeobj); - zval_ptr_dtor(&retval); - return SUCCESS; - } - if (UG(unicode)) { - zval_dtor(&fname); } - break; + return FAILURE; default: break; } @@ -1069,7 +1062,7 @@ ZEND_API zend_object_handlers std_object_handlers = { zend_std_object_get_class, /* get_class_entry */ zend_std_object_get_class_name, /* get_class_name */ zend_std_compare_objects, /* compare_objects */ - NULL, /* cast_object */ + zend_std_cast_object_tostring, /* cast_object */ NULL, /* count_elements */ }; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 7b51bf9833..fb20ffb8fc 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -884,34 +884,28 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMP|VAR|CV, ANY) zend_free_op free_op1; zval z_copy; zval *z = GET_OP1_ZVAL_PTR(BP_VAR_R); - - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL && - zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) { - zend_print_variable(&z_copy); - zval_dtor(&z_copy); - } else { - UErrorCode status = U_ZERO_ERROR; - /* Convert inline HTML blocks to the output encoding, but only if necessary. */ - if (opline->extended_value && - strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status), - EG(active_op_array)->script_encoding)) { - zval z_conv; - UConverter *script_enc_conv = NULL; - if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) { - zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding); - } - zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status); - z_conv.type = IS_BINARY; - if (U_SUCCESS(status)) { - zend_print_variable(&z_conv); - } else { - zend_error(E_WARNING, "Could not convert inline HTML for output"); - } - zval_dtor(&z_conv); - ucnv_close(script_enc_conv); + UErrorCode status = U_ZERO_ERROR; + + /* Convert inline HTML blocks to the output encoding, but only if necessary. */ + if (opline->extended_value && + strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status), + EG(active_op_array)->script_encoding)) { + zval z_conv; + UConverter *script_enc_conv = NULL; + if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) { + zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding); + } + zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status); + z_conv.type = IS_BINARY; + if (U_SUCCESS(status)) { + zend_print_variable(&z_conv); } else { - zend_print_variable(z); + zend_error(E_WARNING, "Could not convert inline HTML for output"); } + zval_dtor(&z_conv); + ucnv_close(script_enc_conv); + } else { + zend_print_variable(z); } FREE_OP1(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 1e4e82bf77..89f4402b31 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1367,34 +1367,28 @@ static int ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval z_copy; zval *z = &opline->op1.u.constant; - - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL && - zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) { - zend_print_variable(&z_copy); - zval_dtor(&z_copy); - } else { - UErrorCode status = U_ZERO_ERROR; - /* Convert inline HTML blocks to the output encoding, but only if necessary. */ - if (opline->extended_value && - strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status), - EG(active_op_array)->script_encoding)) { - zval z_conv; - UConverter *script_enc_conv = NULL; - if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) { - zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding); - } - zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status); - z_conv.type = IS_BINARY; - if (U_SUCCESS(status)) { - zend_print_variable(&z_conv); - } else { - zend_error(E_WARNING, "Could not convert inline HTML for output"); - } - zval_dtor(&z_conv); - ucnv_close(script_enc_conv); + UErrorCode status = U_ZERO_ERROR; + + /* Convert inline HTML blocks to the output encoding, but only if necessary. */ + if (opline->extended_value && + strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status), + EG(active_op_array)->script_encoding)) { + zval z_conv; + UConverter *script_enc_conv = NULL; + if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) { + zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding); + } + zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status); + z_conv.type = IS_BINARY; + if (U_SUCCESS(status)) { + zend_print_variable(&z_conv); } else { - zend_print_variable(z); + zend_error(E_WARNING, "Could not convert inline HTML for output"); } + zval_dtor(&z_conv); + ucnv_close(script_enc_conv); + } else { + zend_print_variable(z); } ZEND_VM_NEXT_OPCODE(); @@ -3879,34 +3873,28 @@ static int ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; zval z_copy; zval *z = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL && - zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) { - zend_print_variable(&z_copy); - zval_dtor(&z_copy); - } else { - UErrorCode status = U_ZERO_ERROR; - /* Convert inline HTML blocks to the output encoding, but only if necessary. */ - if (opline->extended_value && - strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status), - EG(active_op_array)->script_encoding)) { - zval z_conv; - UConverter *script_enc_conv = NULL; - if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) { - zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding); - } - zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status); - z_conv.type = IS_BINARY; - if (U_SUCCESS(status)) { - zend_print_variable(&z_conv); - } else { - zend_error(E_WARNING, "Could not convert inline HTML for output"); - } - zval_dtor(&z_conv); - ucnv_close(script_enc_conv); + UErrorCode status = U_ZERO_ERROR; + + /* Convert inline HTML blocks to the output encoding, but only if necessary. */ + if (opline->extended_value && + strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status), + EG(active_op_array)->script_encoding)) { + zval z_conv; + UConverter *script_enc_conv = NULL; + if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) { + zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding); + } + zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status); + z_conv.type = IS_BINARY; + if (U_SUCCESS(status)) { + zend_print_variable(&z_conv); } else { - zend_print_variable(z); + zend_error(E_WARNING, "Could not convert inline HTML for output"); } + zval_dtor(&z_conv); + ucnv_close(script_enc_conv); + } else { + zend_print_variable(z); } zval_dtor(free_op1.var); @@ -6930,34 +6918,28 @@ static int ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_free_op free_op1; zval z_copy; zval *z = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC); - - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL && - zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) { - zend_print_variable(&z_copy); - zval_dtor(&z_copy); - } else { - UErrorCode status = U_ZERO_ERROR; - /* Convert inline HTML blocks to the output encoding, but only if necessary. */ - if (opline->extended_value && - strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status), - EG(active_op_array)->script_encoding)) { - zval z_conv; - UConverter *script_enc_conv = NULL; - if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) { - zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding); - } - zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status); - z_conv.type = IS_BINARY; - if (U_SUCCESS(status)) { - zend_print_variable(&z_conv); - } else { - zend_error(E_WARNING, "Could not convert inline HTML for output"); - } - zval_dtor(&z_conv); - ucnv_close(script_enc_conv); + UErrorCode status = U_ZERO_ERROR; + + /* Convert inline HTML blocks to the output encoding, but only if necessary. */ + if (opline->extended_value && + strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status), + EG(active_op_array)->script_encoding)) { + zval z_conv; + UConverter *script_enc_conv = NULL; + if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) { + zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding); + } + zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status); + z_conv.type = IS_BINARY; + if (U_SUCCESS(status)) { + zend_print_variable(&z_conv); } else { - zend_print_variable(z); + zend_error(E_WARNING, "Could not convert inline HTML for output"); } + zval_dtor(&z_conv); + ucnv_close(script_enc_conv); + } else { + zend_print_variable(z); } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; @@ -19709,34 +19691,28 @@ static int ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval z_copy; zval *z = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC); - - if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL && - zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) { - zend_print_variable(&z_copy); - zval_dtor(&z_copy); - } else { - UErrorCode status = U_ZERO_ERROR; - /* Convert inline HTML blocks to the output encoding, but only if necessary. */ - if (opline->extended_value && - strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status), - EG(active_op_array)->script_encoding)) { - zval z_conv; - UConverter *script_enc_conv = NULL; - if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) { - zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding); - } - zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status); - z_conv.type = IS_BINARY; - if (U_SUCCESS(status)) { - zend_print_variable(&z_conv); - } else { - zend_error(E_WARNING, "Could not convert inline HTML for output"); - } - zval_dtor(&z_conv); - ucnv_close(script_enc_conv); + UErrorCode status = U_ZERO_ERROR; + + /* Convert inline HTML blocks to the output encoding, but only if necessary. */ + if (opline->extended_value && + strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status), + EG(active_op_array)->script_encoding)) { + zval z_conv; + UConverter *script_enc_conv = NULL; + if (zend_set_converter_encoding(&script_enc_conv, EG(active_op_array)->script_encoding) == FAILURE) { + zend_error(E_ERROR, "Unsupported encoding [%d]", EG(active_op_array)->script_encoding); + } + zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), script_enc_conv, &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status); + z_conv.type = IS_BINARY; + if (U_SUCCESS(status)) { + zend_print_variable(&z_conv); } else { - zend_print_variable(z); + zend_error(E_WARNING, "Could not convert inline HTML for output"); } + zval_dtor(&z_conv); + ucnv_close(script_enc_conv); + } else { + zend_print_variable(z); } ZEND_VM_NEXT_OPCODE(); diff --git a/tests/classes/tostring.phpt b/tests/classes/tostring.phpt index b639183d2f..40876d7292 100644 --- a/tests/classes/tostring.phpt +++ b/tests/classes/tostring.phpt @@ -34,9 +34,11 @@ echo "string:".$o; echo "====test5====\n"; echo 1 . $o; +echo 1 . $o; echo "====test6====\n"; echo $o.$o; +echo $o,$o; echo "====test7====\n"; $ar = array(); @@ -56,8 +58,8 @@ echo sprintf("%s", $o); test1 Object ( ) -string(1%d) "Object id #%d" -object(test1)#%d (%d) { +string(12) "Object id #%d" +object(test1)#%d (0) { } ====test2==== test2 Object @@ -71,26 +73,42 @@ object(test2)#%d (%d) { test2::__toString() Converted ====test4==== -string:Object id #%d====test5==== -1Object id #%d====test6==== -Object id #%dObject id #2====test7==== +test2::__toString() +string:Converted +====test5==== +test2::__toString() +1Converted +test2::__toString() +1Converted +====test6==== +test2::__toString() +test2::__toString() +Converted +Converted +test2::__toString() +Converted +test2::__toString() +Converted +====test7==== test2::__toString() Warning: Illegal offset type in %stostring.php on line %d ====test8==== - -Notice: Object of class test2 to string conversion in %stostring.php on line %d -string(6) "Object" -string(1%d) "Object id #%d" +test2::__toString() +string(9) "Converted" +test2::__toString() +string(9) "Converted" ====test9==== -Object id #%d====DONE!==== +test2::__toString() +Converted +====DONE!==== --UEXPECTF-- ====test1==== test1 Object ( ) -string(1%d) "Object id #%d" -object(test1)#%d (%d) { +string(12) "Object id #%d" +object(test1)#%d (0) { } ====test2==== test2 Object @@ -104,16 +122,32 @@ object(test2)#%d (%d) { test2::__toString() Converted ====test4==== -string:Object id #%d====test5==== -1Object id #%d====test6==== -Object id #%dObject id #2====test7==== +test2::__toString() +string:Converted +====test5==== +test2::__toString() +1Converted +test2::__toString() +1Converted +====test6==== +test2::__toString() +test2::__toString() +Converted +Converted +test2::__toString() +Converted +test2::__toString() +Converted +====test7==== test2::__toString() Warning: Illegal offset type in %stostring.php on line %d ====test8==== - -Notice: Object of class test2 to string conversion in %stostring.php on line %d -unicode(6) "Object" -unicode(1%d) "Object id #%d" +test2::__toString() +unicode(9) "Converted" +test2::__toString() +unicode(9) "Converted" ====test9==== -Object id #%d====DONE!==== +test2::__toString() +Converted +====DONE!==== -- 2.50.1