Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:42.1:Rings:1-MinimalX
php5
php5-finally-exception-crash.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File php5-finally-exception-crash.patch of Package php5
From 794a888a48715af5a97e3af9a8bdd88b20432f53 Mon Sep 17 00:00:00 2001 From: Xinchen Hui <laruence@gmail.com> Date: Fri, 13 Dec 2013 00:15:50 +0800 Subject: [PATCH] Fixed bug #65784 (Segfault with finally). --- Zend/zend_compile.h +++ Zend/zend_compile.h @@ -401,6 +401,7 @@ struct _zend_execute_data { zend_class_entry *current_called_scope; zval *current_this; struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */ + zval *delayed_exception; call_slot *call_slots; call_slot *call; }; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 5aea39e..5c6d3e7 100644 --- Zend/zend_execute.c +++ Zend/zend_execute.c @@ -1650,6 +1650,7 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array EX(call) = NULL; EG(current_execute_data) = execute_data; EX(nested) = nested; + EX(delayed_exception) = NULL; if (!op_array->run_time_cache && op_array->last_cache_slot) { op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index f422443..5385f3e 100644 --- Zend/zend_vm_def.h +++ Zend/zend_vm_def.h @@ -5021,7 +5021,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) { zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes; int i; - zend_uint catch_op_num = 0, finally_op_num = 0; + zend_uint catch_op_num = 0, finally_op_num = 0, finally_op_end = 0; void **stack_frame; /* Figure out where the next stack frame (which maybe contains pushed @@ -5046,6 +5046,10 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) { finally_op_num = EX(op_array)->try_catch_array[i].finally_op; } + if (op_num >= EG(active_op_array)->try_catch_array[i].finally_op && + op_num < EG(active_op_array)->try_catch_array[i].finally_end) { + finally_op_end = EG(active_op_array)->try_catch_array[i].finally_end; + } } if (EX(call) >= EX(call_slots)) { @@ -5107,14 +5111,29 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) EX(old_error_reporting) = NULL; if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { - zend_exception_save(TSRMLS_C); + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + } + EX(delayed_exception) = EG(exception); + EG(exception) = NULL; EX(fast_ret) = NULL; ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } else if (catch_op_num) { + if (finally_op_end && catch_op_num > finally_op_end) { + /* we are going out of current finally scope */ + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + EX(delayed_exception) = NULL; + } + } ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]); ZEND_VM_CONTINUE(); } else { + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + EX(delayed_exception) = NULL; + } if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); } else { @@ -5405,10 +5424,10 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY) { - if (EG(prev_exception) != NULL) { + if (EX(delayed_exception) != NULL) { /* discard the previously thrown exception */ - zval_ptr_dtor(&EG(prev_exception)); - EG(prev_exception) = NULL; + zval_ptr_dtor(&EX(delayed_exception)); + EX(delayed_exception) = NULL; } ZEND_VM_NEXT_OPCODE(); @@ -5425,6 +5444,7 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY) ZEND_VM_CONTINUE(); } EX(fast_ret) = opline + 1; + EX(delayed_exception) = NULL; ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); ZEND_VM_CONTINUE(); } @@ -5441,16 +5461,17 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY) if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); - } else if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { - zend_exception_restore(TSRMLS_C); - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); - ZEND_VM_CONTINUE(); - } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { - zend_exception_restore(TSRMLS_C); - ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); } else { - zend_exception_restore(TSRMLS_C); - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + EG(exception) = EX(delayed_exception); + EX(delayed_exception) = NULL; + if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); + } else { + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + } } } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 77672a3..02f8acb 100644 --- Zend/zend_vm_execute.h +++ Zend/zend_vm_execute.h @@ -1016,7 +1016,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER { zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes; int i; - zend_uint catch_op_num = 0, finally_op_num = 0; + zend_uint catch_op_num = 0, finally_op_num = 0, finally_op_end = 0; void **stack_frame; /* Figure out where the next stack frame (which maybe contains pushed @@ -1041,6 +1041,10 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) { finally_op_num = EX(op_array)->try_catch_array[i].finally_op; } + if (op_num >= EG(active_op_array)->try_catch_array[i].finally_op && + op_num < EG(active_op_array)->try_catch_array[i].finally_end) { + finally_op_end = EG(active_op_array)->try_catch_array[i].finally_end; + } } if (EX(call) >= EX(call_slots)) { @@ -1102,14 +1106,29 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER EX(old_error_reporting) = NULL; if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { - zend_exception_save(TSRMLS_C); + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + } + EX(delayed_exception) = EG(exception); + EG(exception) = NULL; EX(fast_ret) = NULL; ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } else if (catch_op_num) { + if (finally_op_end && catch_op_num > finally_op_end) { + /* we are going out of current finally scope */ + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + EX(delayed_exception) = NULL; + } + } ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]); ZEND_VM_CONTINUE(); } else { + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + EX(delayed_exception) = NULL; + } if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { @@ -1159,10 +1178,10 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS static int ZEND_FASTCALL ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - if (EG(prev_exception) != NULL) { + if (EX(delayed_exception) != NULL) { /* discard the previously thrown exception */ - zval_ptr_dtor(&EG(prev_exception)); - EG(prev_exception) = NULL; + zval_ptr_dtor(&EX(delayed_exception)); + EX(delayed_exception) = NULL; } ZEND_VM_NEXT_OPCODE(); @@ -1179,6 +1198,7 @@ static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_CONTINUE(); } EX(fast_ret) = opline + 1; + EX(delayed_exception) = NULL; ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); ZEND_VM_CONTINUE(); } @@ -1195,16 +1215,17 @@ static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); - } else if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { - zend_exception_restore(TSRMLS_C); - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); - ZEND_VM_CONTINUE(); - } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { - zend_exception_restore(TSRMLS_C); - return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zend_exception_restore(TSRMLS_C); - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + EG(exception) = EX(delayed_exception); + EX(delayed_exception) = NULL; + if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } } } -- 2.0.3
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor