summaryrefslogtreecommitdiff
path: root/Zend/zend_opcode.c
diff options
context:
space:
mode:
authorXinchen Hui <laruence@php.net>2012-08-18 11:44:09 +0800
committerXinchen Hui <laruence@php.net>2012-08-18 11:44:09 +0800
commit72b9b8f380690357fc29efdfcba183b8a8a81268 (patch)
tree426289fce87552fb3da7d0efc4ad91462333c7b1 /Zend/zend_opcode.c
parent7cf9ac1420ecb1b05a7899e50e91772afe3fcdfb (diff)
downloadphp-git-72b9b8f380690357fc29efdfcba183b8a8a81268.tar.gz
Make the codes clearer, and also check continue statement
Diffstat (limited to 'Zend/zend_opcode.c')
-rw-r--r--Zend/zend_opcode.c52
1 files changed, 38 insertions, 14 deletions
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 8cccfe6376..86144d60e1 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -485,6 +485,24 @@ static void zend_extension_op_array_handler(zend_extension *extension, zend_op_a
}
}
+static void zend_check_finally_breakout(zend_op_array *op_array, zend_op *opline, zend_uint dst_num TSRMLS_DC) {
+ zend_uint i, op_num = opline - op_array->opcodes;
+ for (i=0; i < op_array->last_try_catch; i++) {
+ if (op_array->try_catch_array[i].try_op > op_num) {
+ break;
+ }
+ if ((op_num >= op_array->try_catch_array[i].finally_op
+ && op_num < op_array->try_catch_array[i].finally_end)
+ && (dst_num >= op_array->try_catch_array[i].finally_end
+ || dst_num < op_array->try_catch_array[i].finally_op)) {
+ CG(in_compilation) = 1;
+ CG(active_op_array) = op_array;
+ CG(zend_lineno) = opline->lineno;
+ zend_error(E_COMPILE_ERROR, "jump out of a finally block is disallowed");
+ }
+ }
+}
+
ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
{
zend_op *opline, *end;
@@ -529,23 +547,29 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
/* break omitted intentionally */
case ZEND_JMP:
if (op_array->last_try_catch) {
+ zend_check_finally_breakout(op_array, opline, opline->op1.opline_num TSRMLS_CC);
+ }
+ opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
+ break;
+ case ZEND_BRK:
+ case ZEND_CONT:
+ if (op_array->last_try_catch) {
zend_uint i, op_num = opline - op_array->opcodes;
- for (i=0; i < op_array->last_try_catch; i++) {
- if (op_array->try_catch_array[i].try_op > op_num) {
- break;
+ int nest_levels, array_offset;
+ zend_brk_cont_element *jmp_to;
+
+ nest_levels = Z_LVAL_P(opline->op2.zv);
+ array_offset = opline->op1.opline_num;
+ do {
+ jmp_to = &op_array->brk_cont_array[array_offset];
+ if (nest_levels > 1) {
+ array_offset = jmp_to->parent;
}
- if ((op_num >= op_array->try_catch_array[i].finally_op
- && op_num < op_array->try_catch_array[i].finally_end)
- && (opline->op1.opline_num >= op_array->try_catch_array[i].finally_end
- || opline->op1.opline_num < op_array->try_catch_array[i].finally_op)) {
- CG(in_compilation) = 1;
- CG(active_op_array) = op_array;
- CG(zend_lineno) = opline->lineno;
- zend_error(E_COMPILE_ERROR, "jump out of a finally block is disallowed");
- }
- }
+ } while (--nest_levels > 0);
+ if (op_array->last_try_catch) {
+ zend_check_finally_breakout(op_array, opline, jmp_to->brk TSRMLS_CC);
+ }
}
- opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
break;
case ZEND_JMPZ:
case ZEND_JMPNZ: