diff options
author | Marcus Boerger <helly@php.net> | 2003-11-08 14:06:08 +0000 |
---|---|---|
committer | Marcus Boerger <helly@php.net> | 2003-11-08 14:06:08 +0000 |
commit | 316854323d63ed98cb0ce289a5ffd17f9ee938d0 (patch) | |
tree | f70748696fd9420dd73445493f3dccf5e05b9759 | |
parent | ed451570470ebaf24ffe2a2d20403c6749d32318 (diff) | |
download | php-git-316854323d63ed98cb0ce289a5ffd17f9ee938d0.tar.gz |
Handle exceptions in casting more gracefully.
This fixes bug #26166
-rwxr-xr-x | Zend/tests/bug26166.phpt | 67 | ||||
-rw-r--r-- | Zend/zend.c | 6 | ||||
-rw-r--r-- | Zend/zend_object_handlers.c | 9 | ||||
-rw-r--r-- | Zend/zend_operators.c | 10 |
4 files changed, 86 insertions, 6 deletions
diff --git a/Zend/tests/bug26166.phpt b/Zend/tests/bug26166.phpt new file mode 100755 index 0000000000..46a8e3a614 --- /dev/null +++ b/Zend/tests/bug26166.phpt @@ -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 diff --git a/Zend/zend.c b/Zend/zend.c index 2e5d37cfc8..fe0070d4aa 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -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); diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index a371ebfce8..56d212f387 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -869,8 +869,13 @@ 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 (Z_TYPE_P(retval) != IS_STRING) { - zend_error(E_ERROR, "Method %s::__toString() must return a string value", Z_OBJCE_P(readobj)->name); + 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; diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index f95a6f6aeb..453f1f0f5c 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -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); |