From 60dbf7b541eead97dda255b97da3d386c4645195 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 2 Dec 2014 16:05:30 +0300 Subject: [PATCH] Fixed "finally" handling (the bug was introduced by recent removing of EX(delayed_exception)) --- Zend/zend_generators.c | 1 + Zend/zend_vm_def.h | 25 ++++++++++--------------- Zend/zend_vm_execute.h | 25 ++++++++++--------------- 3 files changed, 21 insertions(+), 30 deletions(-) diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 3d95cde44d..2d1810ef78 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -165,6 +165,7 @@ static void zend_generator_dtor_storage(zend_object *object TSRMLS_DC) /* {{{ */ if (finally_op_num) { zval *fast_call = ZEND_CALL_VAR(ex, ex->func->op_array.opcodes[finally_op_end].op1.var); + Z_OBJ_P(fast_call) = NULL; fast_call->u2.lineno = (uint32_t)-1; ex->opline = &ex->func->op_array.opcodes[finally_op_num]; generator->flags |= ZEND_GENERATOR_FORCED_CLOSE; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b64eb6b3cb..9b9260844f 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5457,12 +5457,14 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) uint32_t op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes; int i; uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0; + int in_finally = 0; for (i = 0; i < EX(func)->op_array.last_try_catch; i++) { if (EX(func)->op_array.try_catch_array[i].try_op > op_num) { /* further blocks will not be relevant... */ break; } + in_finally = 0; if (op_num < EX(func)->op_array.try_catch_array[i].catch_op) { catch_op_num = EX(func)->op_array.try_catch_array[i].catch_op; } @@ -5473,6 +5475,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op && op_num < EX(func)->op_array.try_catch_array[i].finally_end) { finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end; + in_finally = 1; } } @@ -5528,7 +5531,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); - if (Z_OBJ_P(fast_call)) { + if (in_finally && Z_OBJ_P(fast_call)) { zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC); } Z_OBJ_P(fast_call) = EG(exception); @@ -5536,20 +5539,9 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) fast_call->u2.lineno = (uint32_t)-1; ZEND_VM_SET_OPCODE(&EX(func)->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 */ - zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); - - if (Z_OBJ_P(fast_call)) { - zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC); - Z_OBJ_P(fast_call) = NULL; - } - } - ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]); - ZEND_VM_CONTINUE(); } else { - if (finally_op_end) { + if (in_finally) { + /* we are going out of current finally scope */ zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); if (Z_OBJ_P(fast_call)) { @@ -5557,7 +5549,10 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) Z_OBJ_P(fast_call) = NULL; } } - if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) { + if (catch_op_num) { + ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]); + ZEND_VM_CONTINUE(); + } else if (UNEXPECTED((EX(func)->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 f42d1fa69d..326b202135 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1201,12 +1201,14 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER uint32_t op_num = EG(opline_before_exception) - EX(func)->op_array.opcodes; int i; uint32_t catch_op_num = 0, finally_op_num = 0, finally_op_end = 0; + int in_finally = 0; for (i = 0; i < EX(func)->op_array.last_try_catch; i++) { if (EX(func)->op_array.try_catch_array[i].try_op > op_num) { /* further blocks will not be relevant... */ break; } + in_finally = 0; if (op_num < EX(func)->op_array.try_catch_array[i].catch_op) { catch_op_num = EX(func)->op_array.try_catch_array[i].catch_op; } @@ -1217,6 +1219,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER if (op_num >= EX(func)->op_array.try_catch_array[i].finally_op && op_num < EX(func)->op_array.try_catch_array[i].finally_end) { finally_op_end = EX(func)->op_array.try_catch_array[i].finally_end; + in_finally = 1; } } @@ -1272,7 +1275,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); - if (Z_OBJ_P(fast_call)) { + if (in_finally && Z_OBJ_P(fast_call)) { zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC); } Z_OBJ_P(fast_call) = EG(exception); @@ -1280,20 +1283,9 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER fast_call->u2.lineno = (uint32_t)-1; ZEND_VM_SET_OPCODE(&EX(func)->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 */ - zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); - - if (Z_OBJ_P(fast_call)) { - zend_exception_set_previous(EG(exception), Z_OBJ_P(fast_call) TSRMLS_CC); - Z_OBJ_P(fast_call) = NULL; - } - } - ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]); - ZEND_VM_CONTINUE(); } else { - if (finally_op_end) { + if (in_finally) { + /* we are going out of current finally scope */ zval *fast_call = EX_VAR(EX(func)->op_array.opcodes[finally_op_end].op1.var); if (Z_OBJ_P(fast_call)) { @@ -1301,7 +1293,10 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER Z_OBJ_P(fast_call) = NULL; } } - if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_GENERATOR) != 0)) { + if (catch_op_num) { + ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op_num]); + ZEND_VM_CONTINUE(); + } else if (UNEXPECTED((EX(func)->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.40.0