From 74869fa67375b8daf772ac30b6b936fd2a2132c6 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 7 Jul 2015 11:45:34 +0300 Subject: [PATCH] Fixed wrong GOTO resolution --- Zend/tests/jump15.phpt | 29 +++++++++++++++++++++++++++++ Zend/zend_compile.c | 20 ++++++++++++++++---- Zend/zend_compile.h | 1 + Zend/zend_vm_def.h | 6 ------ Zend/zend_vm_execute.h | 16 +++++----------- Zend/zend_vm_opcodes.c | 2 +- Zend/zend_vm_opcodes.h | 1 - 7 files changed, 52 insertions(+), 23 deletions(-) create mode 100644 Zend/tests/jump15.phpt diff --git a/Zend/tests/jump15.phpt b/Zend/tests/jump15.phpt new file mode 100644 index 00000000000..456d27785de --- /dev/null +++ b/Zend/tests/jump15.phpt @@ -0,0 +1,29 @@ +--TEST-- +jump 15: goto from loop (forward) +--FILE-- + +--EXPECT-- +1: ok +2: ok +3: ok diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 69d5939e019..e655e8480c9 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -32,6 +32,7 @@ #include "zend_multibyte.h" #include "zend_language_scanner.h" #include "zend_inheritance.h" +#include "zend_vm.h" #define SET_NODE(target, src) do { \ target ## _type = (src)->op_type; \ @@ -3606,7 +3607,7 @@ void zend_resolve_goto_label(zend_op_array *op_array, znode *label_node, zend_op current = CG(context).current_brk_cont; while (current != -1) { if (CG(context).brk_cont_array[current].start >= 0) { - zend_emit_op(NULL, ZEND_NOP, NULL, label_node); + zend_emit_op(NULL, ZEND_NOP, NULL, NULL); } current = CG(context).brk_cont_array[current].parent; } @@ -3658,13 +3659,24 @@ void zend_resolve_goto_label(zend_op_array *op_array, znode *label_node, zend_op if (brk_opline->opcode == ZEND_FREE) { (pass2_opline - free_vars)->opcode = ZEND_FREE; (pass2_opline - free_vars)->op1_type = brk_opline->op1_type; - (pass2_opline - free_vars)->op1.var = brk_opline->op1.var; + if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) { + (pass2_opline - free_vars)->op1.var = brk_opline->op1.var; + } else { + (pass2_opline - free_vars)->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + brk_opline->op1.var); + ZEND_VM_SET_OPCODE_HANDLER(pass2_opline - free_vars); + } + free_vars--; } else if (brk_opline->opcode == ZEND_FE_FREE) { (pass2_opline - free_vars)->opcode = ZEND_FE_FREE; (pass2_opline - free_vars)->op1_type = brk_opline->op1_type; - (pass2_opline - free_vars)->op1.var = brk_opline->op1.var; + if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) { + (pass2_opline - free_vars)->op1.var = brk_opline->op1.var; + } else { + (pass2_opline - free_vars)->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + brk_opline->op1.var); + ZEND_VM_SET_OPCODE_HANDLER(pass2_opline - free_vars); + } + free_vars--; } - free_vars--; } current = CG(context).brk_cont_array[current].parent; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index e72be9cab46..993a19fb6b4 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -958,6 +958,7 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf, #define ZEND_ARRAY_SIZE_SHIFT 2 /* Pseudo-opcodes that are used only temporarily during compilation */ +#define ZEND_GOTO 253 #define ZEND_BRK 254 #define ZEND_CONT 255 diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 623925eddd9..ea2c51a29c0 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -4866,12 +4866,6 @@ ZEND_VM_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST) -{ - zend_error_noreturn(E_ERROR, "GOTO must be resolved at compile-time."); - ZEND_VM_NEXT_OPCODE(); /* Never reached */ -} - ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV) { USE_OPLINE diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index e8aa7bb0151..8dfa511ed90 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -2225,12 +2225,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(Z ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -{ - zend_error_noreturn(E_ERROR, "GOTO must be resolved at compile-time."); - ZEND_VM_NEXT_OPCODE(); /* Never reached */ -} - static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -48403,27 +48397,27 @@ void zend_init_opcodes_handlers(void) ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_GOTO_SPEC_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_GOTO_SPEC_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_GOTO_SPEC_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_GOTO_SPEC_CONST_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, - ZEND_GOTO_SPEC_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, ZEND_NULL_HANDLER, diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index 705ab9cd29c..1f26f0439e4 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -122,7 +122,7 @@ const char *zend_vm_opcodes_map[173] = { "ZEND_FETCH_OBJ_UNSET", "ZEND_FETCH_LIST", "ZEND_FETCH_CONSTANT", - "ZEND_GOTO", + NULL, "ZEND_EXT_STMT", "ZEND_EXT_FCALL_BEGIN", "ZEND_EXT_FCALL_END", diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index f6de5b1b577..bb2d7717bdc 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -130,7 +130,6 @@ END_EXTERN_C() #define ZEND_FETCH_OBJ_UNSET 97 #define ZEND_FETCH_LIST 98 #define ZEND_FETCH_CONSTANT 99 -#define ZEND_GOTO 100 #define ZEND_EXT_STMT 101 #define ZEND_EXT_FCALL_BEGIN 102 #define ZEND_EXT_FCALL_END 103