Skip to content

Commit 0e39187

Browse files
committed
Provide string casting for exceptions by calling toString()
1 parent e3929cc commit 0e39187

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

Zend/zend_default_classes.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
#include "zend_reflection_api.h"
2525
#include "zend_builtin_functions.h"
2626

27-
zend_class_entry *default_exception_ptr;
27+
static zend_class_entry *default_exception_ptr;
28+
static zend_object_handlers default_exception_handlers;
2829

2930
static zend_object_value zend_default_exception_new(zend_class_entry *class_type TSRMLS_DC)
3031
{
@@ -33,6 +34,7 @@ static zend_object_value zend_default_exception_new(zend_class_entry *class_type
3334
zval *trace;
3435

3536
obj.value.obj = zend_objects_new(&object, class_type TSRMLS_CC);
37+
obj.value.obj.handlers = &default_exception_handlers;
3638

3739
ALLOC_HASHTABLE(object->properties);
3840
zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
@@ -356,13 +358,30 @@ static zend_function_entry default_exception_functions[] = {
356358
{NULL, NULL, NULL}
357359
};
358360

361+
void zend_cast_exception(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC)
362+
{
363+
if (type == IS_STRING) {
364+
zval fname, *retval;
365+
366+
ZVAL_STRING(&fname, "tostring", 0);
367+
if (call_user_function_ex(NULL, &readobj, &fname, &retval, 0, NULL, 0, NULL TSRMLS_CC) == SUCCESS) {
368+
ZVAL_STRING(writeobj, Z_STRVAL_P(retval), 1);
369+
zval_ptr_dtor(&retval);
370+
return;
371+
}
372+
}
373+
Z_TYPE_P(writeobj) = IS_NULL;
374+
}
375+
359376
static void zend_register_default_exception(TSRMLS_D)
360377
{
361378
zend_class_entry ce;
362379

363380
INIT_CLASS_ENTRY(ce, "exception", default_exception_functions);
364381
default_exception_ptr = zend_register_internal_class(&ce TSRMLS_CC);
365-
default_exception_ptr->create_object = zend_default_exception_new;
382+
default_exception_ptr->create_object = zend_default_exception_new;
383+
memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
384+
default_exception_handlers.cast_object = zend_cast_exception;
366385

367386
zend_declare_property_string(default_exception_ptr, "message", sizeof("message")-1, "Unknown exception", ZEND_ACC_PROTECTED TSRMLS_CC);
368387
zend_declare_property_string(default_exception_ptr, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);

Zend/zend_exceptions.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
#include "zend_reflection_api.h"
2525
#include "zend_builtin_functions.h"
2626

27-
zend_class_entry *default_exception_ptr;
27+
static zend_class_entry *default_exception_ptr;
28+
static zend_object_handlers default_exception_handlers;
2829

2930
static zend_object_value zend_default_exception_new(zend_class_entry *class_type TSRMLS_DC)
3031
{
@@ -33,6 +34,7 @@ static zend_object_value zend_default_exception_new(zend_class_entry *class_type
3334
zval *trace;
3435

3536
obj.value.obj = zend_objects_new(&object, class_type TSRMLS_CC);
37+
obj.value.obj.handlers = &default_exception_handlers;
3638

3739
ALLOC_HASHTABLE(object->properties);
3840
zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
@@ -356,13 +358,30 @@ static zend_function_entry default_exception_functions[] = {
356358
{NULL, NULL, NULL}
357359
};
358360

361+
void zend_cast_exception(zval *readobj, zval *writeobj, int type, int should_free TSRMLS_DC)
362+
{
363+
if (type == IS_STRING) {
364+
zval fname, *retval;
365+
366+
ZVAL_STRING(&fname, "tostring", 0);
367+
if (call_user_function_ex(NULL, &readobj, &fname, &retval, 0, NULL, 0, NULL TSRMLS_CC) == SUCCESS) {
368+
ZVAL_STRING(writeobj, Z_STRVAL_P(retval), 1);
369+
zval_ptr_dtor(&retval);
370+
return;
371+
}
372+
}
373+
Z_TYPE_P(writeobj) = IS_NULL;
374+
}
375+
359376
static void zend_register_default_exception(TSRMLS_D)
360377
{
361378
zend_class_entry ce;
362379

363380
INIT_CLASS_ENTRY(ce, "exception", default_exception_functions);
364381
default_exception_ptr = zend_register_internal_class(&ce TSRMLS_CC);
365-
default_exception_ptr->create_object = zend_default_exception_new;
382+
default_exception_ptr->create_object = zend_default_exception_new;
383+
memcpy(&default_exception_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
384+
default_exception_handlers.cast_object = zend_cast_exception;
366385

367386
zend_declare_property_string(default_exception_ptr, "message", sizeof("message")-1, "Unknown exception", ZEND_ACC_PROTECTED TSRMLS_CC);
368387
zend_declare_property_string(default_exception_ptr, "string", sizeof("string")-1, "", ZEND_ACC_PRIVATE TSRMLS_CC);

0 commit comments

Comments
 (0)