From 034d2e59169176a169c6352c0cb01acb4957d66a Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Fri, 8 Aug 2008 17:10:49 +0000 Subject: [PATCH] - Turns out the easy solution for correct error_handling doesn't work. So we need to provide save/replace/restore functions right away. It also to save/restore in the vm. --- Zend/zend.h | 9 +++++++++ Zend/zend_API.c | 31 +++++++++++++++++++++++++++++++ Zend/zend_execute_API.c | 17 +++++++---------- Zend/zend_vm_def.h | 6 ++++++ Zend/zend_vm_execute.h | 6 ++++++ main/main.c | 15 --------------- main/php.h | 5 ++++- 7 files changed, 63 insertions(+), 26 deletions(-) diff --git a/Zend/zend.h b/Zend/zend.h index 8bb845a8669e2..c890cb240b44c 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -802,6 +802,15 @@ typedef enum { EH_THROW } zend_error_handling_t; +typedef struct { + zend_error_handling_t handling; + zend_class_entry *exception; +} zend_error_handling; + +ZEND_API void zend_save_error_handling(zend_error_handling *current TSRMLS_DC); +ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current TSRMLS_DC); +ZEND_API void zend_restore_error_handling(const zend_error_handling *saved TSRMLS_DC); + #define ZEND_U_EQUAL(type, ustr, ulen, str, slen) \ ((type == IS_STRING)? \ (!memcmp((ustr).s,(str),(slen))): \ diff --git a/Zend/zend_API.c b/Zend/zend_API.c index b142c1f1bb10c..b4bda2c1864ee 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -4285,6 +4285,37 @@ ZEND_API zend_uchar zend_get_unified_string_type(int num_args TSRMLS_DC, ...) /* } /* }}} */ +ZEND_API void zend_save_error_handling(zend_error_handling *current TSRMLS_DC) /* {{{ */ +{ + current->handling = EG(error_handling); + current->exception = EG(exception_class); +} +/* }}} */ + +ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current TSRMLS_DC) /* {{{ */ +{ + if (current) { + zend_save_error_handling(current TSRMLS_CC); + } + EG(error_handling) = error_handling; + EG(exception_class) = error_handling == EH_THROW ? exception_class : NULL; + + if (error_handling == EH_NORMAL) { + EG(user_error_handler) = EG(user_error_handler_old); + } else { + EG(user_error_handler_old) = EG(user_error_handler); + EG(user_error_handler) = NULL; + } +} +/* }}} */ + +ZEND_API void zend_restore_error_handling(const zend_error_handling *saved TSRMLS_DC) /* {{{ */ +{ + EG(error_handling) = saved->handling; + EG(exception_class) = saved->handling == EH_THROW ? saved->exception : NULL; +} +/* }}} */ + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 94a5d3427c495..92ed55654092e 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -947,16 +947,14 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS EG(opline_ptr) = original_opline_ptr; } else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0; - zend_error_handling_t error_handling = EG(error_handling); - zend_class_entry *exception_class = EG(exception_class); - + zend_error_handling error_handling; + zend_save_error_handling(&error_handling TSRMLS_CC); ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr); if (EX(function_state).function->common.scope) { EG(scope) = EX(function_state).function->common.scope; } ((zend_internal_function *) EX(function_state).function)->handler(fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, (fci->object_pp?*fci->object_pp:NULL), 1 TSRMLS_CC); - EG(error_handling) = error_handling; - EG(exception_class) = exception_class; + zend_restore_error_handling(&error_handling TSRMLS_CC); /* We shouldn't fix bad extensions here, because it can break proper ones (Bug #34045) if (!EX(function_state).function->common.return_reference) @@ -975,13 +973,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS } else { /* ZEND_OVERLOADED_FUNCTION */ ALLOC_INIT_ZVAL(*fci->retval_ptr_ptr); - /* Not sure what should be done here if it's a static method */ + /* Not sure what should be done here if it's a static method */ if (fci->object_pp) { - zend_error_handling_t error_handling = EG(error_handling); - zend_class_entry *exception_class = EG(exception_class); + zend_error_handling error_handling; + zend_save_error_handling(&error_handling TSRMLS_CC); Z_OBJ_HT_PP(fci->object_pp)->call_method(EX(function_state).function->common.function_name, fci->param_count, *fci->retval_ptr_ptr, fci->retval_ptr_ptr, *fci->object_pp, 1 TSRMLS_CC); - EG(error_handling) = error_handling; - EG(exception_class) = exception_class; + zend_restore_error_handling(&error_handling TSRMLS_CC); } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index c27761f3b72ea..efea17dd9f7ca 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2337,6 +2337,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) EX(function_state).arguments = zend_vm_stack_push_args(opline->extended_value TSRMLS_CC); if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { + zend_error_handling error_handling; ALLOC_INIT_ZVAL(EX_T(opline->result.u.var).var.ptr); EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; EX_T(opline->result.u.var).var.fcall_returned_reference = EX(function_state).function->common.return_reference; @@ -2351,12 +2352,14 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) arg_count--; } } + zend_save_error_handling(&error_handling TSRMLS_CC); if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ ((zend_internal_function *) EX(function_state).function)->handler(opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); } else { zend_execute_internal(EXECUTE_DATA, RETURN_VALUE_USED(opline) TSRMLS_CC); } + zend_restore_error_handling(&error_handling TSRMLS_CC); if (!RETURN_VALUE_USED(opline)) { zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr); @@ -2404,7 +2407,10 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) /* Not sure what should be done here if it's a static method */ if (EX(object)) { + zend_error_handling error_handling; + zend_save_error_handling(&error_handling TSRMLS_CC); Z_OBJ_HT_P(EX(object))->call_method(EX(function_state).function->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); + zend_restore_error_handling(&error_handling TSRMLS_CC); } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 9f5f8b28cdc39..1420a54bc51e6 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -302,6 +302,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR EX(function_state).arguments = zend_vm_stack_push_args(opline->extended_value TSRMLS_CC); if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { + zend_error_handling error_handling; ALLOC_INIT_ZVAL(EX_T(opline->result.u.var).var.ptr); EX_T(opline->result.u.var).var.ptr_ptr = &EX_T(opline->result.u.var).var.ptr; EX_T(opline->result.u.var).var.fcall_returned_reference = EX(function_state).function->common.return_reference; @@ -316,12 +317,14 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR arg_count--; } } + zend_save_error_handling(&error_handling TSRMLS_CC); if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ ((zend_internal_function *) EX(function_state).function)->handler(opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); } else { zend_execute_internal(execute_data, RETURN_VALUE_USED(opline) TSRMLS_CC); } + zend_restore_error_handling(&error_handling TSRMLS_CC); if (!RETURN_VALUE_USED(opline)) { zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr); @@ -369,7 +372,10 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR /* Not sure what should be done here if it's a static method */ if (EX(object)) { + zend_error_handling error_handling; + zend_save_error_handling(&error_handling TSRMLS_CC); Z_OBJ_HT_P(EX(object))->call_method(EX(function_state).function->common.function_name, opline->extended_value, EX_T(opline->result.u.var).var.ptr, &EX_T(opline->result.u.var).var.ptr, EX(object), RETURN_VALUE_USED(opline) TSRMLS_CC); + zend_restore_error_handling(&error_handling TSRMLS_CC); } else { zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object"); } diff --git a/main/main.c b/main/main.c index a3ef6f22ea946..1ba177eddf325 100644 --- a/main/main.c +++ b/main/main.c @@ -877,21 +877,6 @@ PHPAPI void php_html_puts(const char *str, uint size TSRMLS_DC) } /* }}} */ -/* {{{ php_suppress_errors */ -PHPAPI void php_set_error_handling(error_handling_t error_handling, zend_class_entry *exception_class TSRMLS_DC) -{ - EG(error_handling) = error_handling; - EG(exception_class) = exception_class; - - if (error_handling == EH_NORMAL) { - EG(user_error_handler) = EG(user_error_handler_old); - } else { - EG(user_error_handler_old) = EG(user_error_handler); - EG(user_error_handler) = NULL; - } -} -/* }}} */ - /* {{{ php_error_cb extended error handling function */ static void php_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) diff --git a/main/php.h b/main/php.h index b56ccc4a835fe..ae70c5c15099f 100644 --- a/main/php.h +++ b/main/php.h @@ -286,7 +286,10 @@ END_EXTERN_C() #define error_handling_t zend_error_handling_t BEGIN_EXTERN_C() -PHPAPI void php_set_error_handling(error_handling_t error_handling, zend_class_entry *exception_class TSRMLS_DC); +static inline ZEND_ATTRIBUTE_DEPRECATED void php_set_error_handling(error_handling_t error_handling, zend_class_entry *exception_class TSRMLS_DC) +{ + zend_replace_error_handling(error_handling, exception_class, NULL TSRMLS_CC); +} static inline ZEND_ATTRIBUTE_DEPRECATED void php_std_error_handling() {} PHPAPI void php_verror(const char *docref, const char *params, int type, const char *format, va_list args TSRMLS_DC);