Fixed wrong GOTO resolution

This commit is contained in:
Dmitry Stogov 2015-07-07 11:45:34 +03:00
parent b0f419540a
commit 74869fa673
7 changed files with 52 additions and 23 deletions

29
Zend/tests/jump15.phpt Normal file
View File

@ -0,0 +1,29 @@
--TEST--
jump 15: goto from loop (forward)
--FILE--
<?php
$ar = array("1","2","3");
foreach ($ar as $val) {
switch ($val) {
case "1":
echo "1: ok\n";
break;
case "2":
echo "2: ok\n";
goto L1;
case "3":
echo "bug\n";
break;
}
}
echo "bug\n";
L1:
try {
echo "3: ok\n";
} finally {
}
?>
--EXPECT--
1: ok
2: ok
3: ok

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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",

View File

@ -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