mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
parent
ed45157047
commit
316854323d
4 changed files with 86 additions and 6 deletions
67
Zend/tests/bug26166.phpt
Executable file
67
Zend/tests/bug26166.phpt
Executable file
|
@ -0,0 +1,67 @@
|
|||
--TEST--
|
||||
Bug #26166: __toString() crash when no values returned
|
||||
--FILE--
|
||||
<?php
|
||||
class Foo
|
||||
{
|
||||
function __toString()
|
||||
{
|
||||
return "Hello World!\n";
|
||||
}
|
||||
}
|
||||
|
||||
class Bar
|
||||
{
|
||||
private $obj;
|
||||
|
||||
function __construct()
|
||||
{
|
||||
$this->obj = new Foo();
|
||||
}
|
||||
|
||||
function __toString()
|
||||
{
|
||||
return $this->obj->__toString();
|
||||
}
|
||||
}
|
||||
|
||||
$o = new Bar;
|
||||
echo $o;
|
||||
|
||||
echo "===THROW===\n";
|
||||
|
||||
class Error
|
||||
{
|
||||
function __toString() {
|
||||
throw new Exception("This is an error!");
|
||||
}
|
||||
}
|
||||
|
||||
$o = new Error;
|
||||
try {
|
||||
echo $o;
|
||||
}
|
||||
catch (Exception $e) {
|
||||
echo "Got the exception\n";
|
||||
}
|
||||
|
||||
echo "===NONE===\n";
|
||||
|
||||
class None
|
||||
{
|
||||
function __toString() {
|
||||
}
|
||||
}
|
||||
|
||||
$o = new None;
|
||||
echo $o;
|
||||
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECTF--
|
||||
Hello World!
|
||||
===THROW===
|
||||
Got the exception
|
||||
===NONE===
|
||||
|
||||
Fatal error: Method none::__toString() must return a string value in %sbug26166.php on line %d
|
|
@ -230,6 +230,12 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
|
|||
if (expr->value.obj.handlers->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 = empty_string;
|
||||
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);
|
||||
|
|
|
@ -869,9 +869,14 @@ int zend_std_cast_object(zval *readobj, zval *writeobj, int type, int should_fre
|
|||
case IS_STRING:
|
||||
ZVAL_STRING(&fname, "__tostring", 0);
|
||||
if (call_user_function_ex(NULL, &readobj, &fname, &retval, 0, NULL, 0, NULL TSRMLS_CC) == SUCCESS) {
|
||||
if (retval) {
|
||||
if (Z_TYPE_P(retval) != IS_STRING) {
|
||||
zend_error(E_ERROR, "Method %s::__toString() must return a string value", Z_OBJCE_P(readobj)->name);
|
||||
}
|
||||
} else {
|
||||
MAKE_STD_ZVAL(retval);
|
||||
ZVAL_STRINGL(retval, empty_string, 0, 0);
|
||||
}
|
||||
REPLACE_ZVAL_VALUE(&writeobj, retval, 0);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
|
|
@ -445,7 +445,6 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
|
|||
{
|
||||
long lval;
|
||||
double dval;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
switch (op->type) {
|
||||
case IS_NULL:
|
||||
|
@ -465,6 +464,7 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
|
|||
break;
|
||||
case IS_RESOURCE: {
|
||||
long tmp = op->value.lval;
|
||||
TSRMLS_FETCH();
|
||||
|
||||
zend_list_delete(op->value.lval);
|
||||
op->value.str.val = (char *) emalloc(sizeof("Resource id #")-1 + MAX_LENGTH_OF_LONG);
|
||||
|
@ -478,6 +478,7 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
|
|||
op->value.str.len = zend_sprintf(op->value.str.val, "%ld", lval); /* SAFE */
|
||||
break;
|
||||
case IS_DOUBLE: {
|
||||
TSRMLS_FETCH();
|
||||
dval = op->value.dval;
|
||||
op->value.str.val = (char *) emalloc_rel(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1);
|
||||
op->value.str.len = zend_sprintf(op->value.str.val, "%.*G", (int) EG(precision), dval); /* SAFE */
|
||||
|
@ -490,11 +491,11 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
|
|||
op->value.str.val = estrndup_rel("Array", sizeof("Array")-1);
|
||||
op->value.str.len = sizeof("Array")-1;
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
case IS_OBJECT: {
|
||||
TSRMLS_FETCH();
|
||||
if (op->value.obj.handlers->cast_object) {
|
||||
zval tmp;
|
||||
TSRMLS_FETCH();
|
||||
if (op->value.obj.handlers->cast_object(op, &tmp, IS_STRING, 1 TSRMLS_CC) == SUCCESS) {
|
||||
if (op->value.obj.handlers->cast_object(op, &tmp, IS_STRING, 1 TSRMLS_CC) == SUCCESS && tmp.type == IS_STRING) {
|
||||
zval_dtor(op);
|
||||
*op = tmp;
|
||||
break;
|
||||
|
@ -507,6 +508,7 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
|
|||
op->value.str.val = estrndup_rel("Object", sizeof("Object")-1);
|
||||
op->value.str.len = sizeof("Object")-1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
zval_dtor(op);
|
||||
ZVAL_BOOL(op, 0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue