Permalink
Browse files

- MFH Improve exception linking

  • Loading branch information...
1 parent 261b4d0 commit 32f9d0e180af2d809bf70e40850fc75e6d663945 Marcus Boerger committed Aug 14, 2008
Showing with 73 additions and 39 deletions.
  1. +9 −12 Zend/zend.c
  2. +36 −8 Zend/zend_exceptions.c
  3. +3 −1 Zend/zend_exceptions.h
  4. +5 −5 Zend/zend_execute_API.c
  5. +1 −1 Zend/zend_globals.h
  6. +5 −4 Zend/zend_objects.c
  7. +3 −0 Zend/zend_vm_def.h
  8. +9 −0 Zend/zend_vm_execute.h
  9. +2 −8 ext/spl/php_spl.c
View
@@ -1197,31 +1197,28 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
if (EG(active_op_array)) {
EG(return_value_ptr_ptr) = retval ? retval : NULL;
zend_execute(EG(active_op_array) TSRMLS_CC);
+ zend_exception_restore(TSRMLS_C);
if (EG(exception)) {
if (EG(user_exception_handler)) {
zval *orig_user_exception_handler;
- zval ***params, *retval2, *old_exception;
- params = (zval ***)emalloc(sizeof(zval **));
+ zval **params[1], *retval2, *old_exception;
old_exception = EG(exception);
- EG(exception) = NULL;
+ zend_exception_save(TSRMLS_C);
params[0] = &old_exception;
orig_user_exception_handler = EG(user_exception_handler);
if (call_user_function_ex(CG(function_table), NULL, orig_user_exception_handler, &retval2, 1, params, 1, NULL TSRMLS_CC) == SUCCESS) {
if (retval2 != NULL) {
zval_ptr_dtor(&retval2);
}
- } else {
- if (!EG(exception)) {
- EG(exception) = old_exception;
+ zend_exception_restore(TSRMLS_C);
+ if (EG(exception)) {
+ zval_ptr_dtor(&EG(exception));
+ EG(exception) = NULL;
}
+ } else {
+ zend_exception_restore(TSRMLS_C);
zend_exception_error(EG(exception) TSRMLS_CC);
}
- efree(params);
- zval_ptr_dtor(&old_exception);
- if (EG(exception)) {
- zval_ptr_dtor(&EG(exception));
- EG(exception) = NULL;
- }
} else {
zend_exception_error(EG(exception) TSRMLS_CC);
}
@@ -33,21 +33,17 @@ zend_class_entry *error_exception_ce;
static zend_object_handlers default_exception_handlers;
ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
-void zend_exception_set_previous(zval *add_previous TSRMLS_DC)
+void zend_exception_set_previous(zval *exception, zval *add_previous TSRMLS_DC)
{
- zval *exception = EG(exception), *previous;
+ zval *previous;
- if (exception == add_previous || !add_previous) {
+ if (exception == add_previous || !add_previous || !exception) {
return;
}
if (Z_TYPE_P(add_previous) != IS_OBJECT && !instanceof_function(Z_OBJCE_P(add_previous), default_exception_ce TSRMLS_CC)) {
zend_error(E_ERROR, "Cannot set non exception as previous exception");
return;
}
- if (!exception) {
- EG(exception) = add_previous;
- return;
- }
while (exception && exception != add_previous && Z_OBJ_HANDLE_P(exception) != Z_OBJ_HANDLE_P(add_previous)) {
previous = zend_read_property(default_exception_ce, exception, "previous", sizeof("previous")-1, 1 TSRMLS_CC);
if (Z_TYPE_P(previous) == IS_NULL) {
@@ -59,12 +55,40 @@ void zend_exception_set_previous(zval *add_previous TSRMLS_DC)
}
}
+void zend_exception_save(TSRMLS_D) /* {{{ */
+{
+ if (EG(prev_exception)) {
+ zend_exception_set_previous(EG(exception), EG(prev_exception) TSRMLS_CC);
+ }
+ if (EG(exception)) {
+ EG(prev_exception) = EG(exception);
+ }
+ EG(exception) = NULL;
+}
+/* }}} */
+
+void zend_exception_restore(TSRMLS_D) /* {{{ */
+{
+ if (EG(prev_exception)) {
+ if (EG(exception)) {
+ zend_exception_set_previous(EG(exception), EG(prev_exception) TSRMLS_CC);
+ } else {
+ EG(exception) = EG(prev_exception);
+ }
+ EG(prev_exception) = NULL;
+ }
+}
+/* }}} */
+
void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
{
if (exception != NULL) {
zval *previous = EG(exception);
+ zend_exception_set_previous(exception, EG(exception) TSRMLS_CC);
EG(exception) = exception;
- zend_exception_set_previous(previous TSRMLS_CC);
+ if (previous) {
+ return;
+ }
}
if (!EG(current_execute_data)) {
zend_error(E_ERROR, "Exception thrown without a stack frame");
@@ -86,6 +110,10 @@ void zend_throw_exception_internal(zval *exception TSRMLS_DC) /* {{{ */
ZEND_API void zend_clear_exception(TSRMLS_D) /* {{{ */
{
+ if (EG(prev_exception)) {
+ zval_ptr_dtor(&EG(prev_exception));
+ EG(prev_exception) = NULL;
+ }
if (!EG(exception)) {
return;
}
@@ -26,7 +26,9 @@
BEGIN_EXTERN_C()
-ZEND_API void zend_exception_set_previous(zval *add_previous TSRMLS_DC);
+ZEND_API void zend_exception_set_previous(zval *exception, zval *add_previous TSRMLS_DC);
+ZEND_API void zend_exception_save(TSRMLS_D);
+ZEND_API void zend_exception_restore(TSRMLS_D);
void zend_throw_exception_internal(zval *exception TSRMLS_DC);
@@ -186,6 +186,7 @@ void init_executor(TSRMLS_D) /* {{{ */
#endif
EG(exception) = NULL;
+ EG(prev_exception) = NULL;
EG(scope) = NULL;
EG(called_scope) = NULL;
@@ -1029,7 +1030,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
fcall_cache.object_pp = NULL;
exception = EG(exception);
- EG(exception) = NULL;
+ zend_exception_save(TSRMLS_C);
retval = zend_call_function(&fcall_info, &fcall_cache TSRMLS_CC);
EG(autoload_func) = fcall_cache.function_handler;
@@ -1038,19 +1039,18 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut
zend_hash_del(EG(in_autoload), lc_name, name_length + 1);
if (retval == FAILURE) {
- EG(exception) = exception;
+ zend_exception_restore(TSRMLS_C);
free_alloca(lc_free, use_heap);
return FAILURE;
}
if (EG(exception) && exception) {
+ zend_exception_restore(TSRMLS_C);
free_alloca(lc_free, use_heap);
zend_error(E_ERROR, "Function %s(%s) threw an exception of type '%s'", ZEND_AUTOLOAD_FUNC_NAME, name, Z_OBJCE_P(EG(exception))->name);
return FAILURE;
}
- if (!EG(exception)) {
- EG(exception) = exception;
- }
+ zend_exception_restore(TSRMLS_C);
if (retval_ptr) {
zval_ptr_dtor(&retval_ptr);
}
View
@@ -239,7 +239,7 @@ struct _zend_executor_globals {
HashTable *modified_ini_directives;
zend_objects_store objects_store;
- zval *exception;
+ zval *exception, *prev_exception;
zend_op *opline_before_exception;
zend_op exception_op[3];
View
@@ -53,7 +53,6 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
if (destructor) {
zval *obj;
- zval *old_exception;
if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) {
if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
@@ -96,10 +95,12 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
* For example, if an exception was thrown in a function and when the function's
* local variable destruction results in a destructor being called.
*/
- old_exception = EG(exception);
- EG(exception) = NULL;
+ if (EG(exception) && Z_OBJ_HANDLE_P(EG(exception)) == handle) {
+ zend_error(E_ERROR, "Attempt to destruct pending exception");
+ }
+ zend_exception_save(TSRMLS_C);
zend_call_method_with_0_params(&obj, object->ce, &destructor, ZEND_DESTRUCTOR_FUNC_NAME, NULL);
- zend_exception_set_previous(old_exception TSRMLS_CC);
+ zend_exception_restore(TSRMLS_C);
zval_ptr_dtor(&obj);
}
}
View
@@ -2515,6 +2515,7 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY)
if (Z_TYPE_P(value) != IS_OBJECT) {
zend_error_noreturn(E_ERROR, "Can only throw objects");
}
+ zend_exception_save(TSRMLS_C);
/* Not sure if a complete copy is what we want here */
ALLOC_ZVAL(exception);
INIT_PZVAL_COPY(exception, value);
@@ -2523,6 +2524,7 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY)
}
zend_throw_exception_object(exception TSRMLS_CC);
+ zend_exception_restore(TSRMLS_C);
FREE_OP1_IF_VAR();
ZEND_VM_NEXT_OPCODE();
}
@@ -2533,6 +2535,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, ANY, CV)
zend_class_entry *ce;
/* Check whether an exception has been thrown, if not, jump over code */
+ zend_exception_restore(TSRMLS_C);
if (EG(exception) == NULL) {
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
@@ -1228,6 +1228,7 @@ static int ZEND_FASTCALL ZEND_CATCH_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_class_entry *ce;
/* Check whether an exception has been thrown, if not, jump over code */
+ zend_exception_restore(TSRMLS_C);
if (EG(exception) == NULL) {
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->extended_value]);
ZEND_VM_CONTINUE(); /* CHECK_ME */
@@ -1655,6 +1656,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
if (Z_TYPE_P(value) != IS_OBJECT) {
zend_error_noreturn(E_ERROR, "Can only throw objects");
}
+ zend_exception_save(TSRMLS_C);
/* Not sure if a complete copy is what we want here */
ALLOC_ZVAL(exception);
INIT_PZVAL_COPY(exception, value);
@@ -1663,6 +1665,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
zend_throw_exception_object(exception TSRMLS_CC);
+ zend_exception_restore(TSRMLS_C);
ZEND_VM_NEXT_OPCODE();
}
@@ -4936,6 +4939,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (Z_TYPE_P(value) != IS_OBJECT) {
zend_error_noreturn(E_ERROR, "Can only throw objects");
}
+ zend_exception_save(TSRMLS_C);
/* Not sure if a complete copy is what we want here */
ALLOC_ZVAL(exception);
INIT_PZVAL_COPY(exception, value);
@@ -4944,6 +4948,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
zend_throw_exception_object(exception TSRMLS_CC);
+ zend_exception_restore(TSRMLS_C);
ZEND_VM_NEXT_OPCODE();
}
@@ -8121,6 +8126,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (Z_TYPE_P(value) != IS_OBJECT) {
zend_error_noreturn(E_ERROR, "Can only throw objects");
}
+ zend_exception_save(TSRMLS_C);
/* Not sure if a complete copy is what we want here */
ALLOC_ZVAL(exception);
INIT_PZVAL_COPY(exception, value);
@@ -8129,6 +8135,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
zend_throw_exception_object(exception TSRMLS_CC);
+ zend_exception_restore(TSRMLS_C);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
ZEND_VM_NEXT_OPCODE();
}
@@ -22193,6 +22200,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (Z_TYPE_P(value) != IS_OBJECT) {
zend_error_noreturn(E_ERROR, "Can only throw objects");
}
+ zend_exception_save(TSRMLS_C);
/* Not sure if a complete copy is what we want here */
ALLOC_ZVAL(exception);
INIT_PZVAL_COPY(exception, value);
@@ -22201,6 +22209,7 @@ static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
zend_throw_exception_object(exception TSRMLS_CC);
+ zend_exception_restore(TSRMLS_C);
ZEND_VM_NEXT_OPCODE();
}
View
@@ -381,7 +381,6 @@ PHP_FUNCTION(spl_autoload_call)
if (SPL_G(autoload_functions)) {
int l_autoload_running = SPL_G(autoload_running);
- zval *exception = NULL;
SPL_G(autoload_running) = 1;
class_name_len = Z_STRLEN_P(class_name);
lc_name = zend_str_tolower_dup(Z_STRVAL_P(class_name), class_name_len);
@@ -390,12 +389,7 @@ PHP_FUNCTION(spl_autoload_call)
zend_hash_get_current_key_ex(SPL_G(autoload_functions), &func_name, &func_name_len, &dummy, 0, &function_pos);
zend_hash_get_current_data_ex(SPL_G(autoload_functions), (void **) &alfi, &function_pos);
zend_call_method(alfi->obj ? &alfi->obj : NULL, alfi->ce, &alfi->func_ptr, func_name, func_name_len, &retval, 1, class_name, NULL TSRMLS_CC);
- zend_exception_set_previous(exception TSRMLS_CC);
- if (EG(exception)) {
- zend_exception_set_previous(exception TSRMLS_CC);
- exception = EG(exception);
- EG(exception) = NULL;
- }
+ zend_exception_save(TSRMLS_C);
if (retval) {
zval_ptr_dtor(&retval);
}
@@ -404,7 +398,7 @@ PHP_FUNCTION(spl_autoload_call)
}
zend_hash_move_forward_ex(SPL_G(autoload_functions), &function_pos);
}
- EG(exception) = exception;
+ zend_exception_restore(TSRMLS_C);
efree(lc_name);
SPL_G(autoload_running) = l_autoload_running;
} else {

0 comments on commit 32f9d0e

Please sign in to comment.