Skip to content

Commit 72b9b8f

Browse files
committed
Make the codes clearer, and also check continue statement
1 parent 7cf9ac1 commit 72b9b8f

File tree

5 files changed

+67
-23
lines changed

5 files changed

+67
-23
lines changed

Zend/tests/try_finally_008.phpt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,12 @@ function foo () {
77
try {
88
try {
99
} finally {
10-
goto label;
11-
echo "dummy";
10+
break;
1211
}
1312
} catch (Exception $e) {
1413
} finally {
1514
}
1615
} while (0);
17-
label:
18-
echo "label";
1916
}
2017

2118
foo();

Zend/tests/try_finally_009.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Finally with jmp (for continue)
3+
--FILE--
4+
<?php
5+
function foo () {
6+
for($i = 0; $i < 5; $i++) {
7+
do {
8+
try {
9+
try {
10+
} finally {
11+
}
12+
} catch (Exception $e) {
13+
} finally {
14+
continue;
15+
}
16+
} while (0);
17+
}
18+
}
19+
20+
foo();
21+
?>
22+
--EXPECTF--
23+
Fatal error: jump out of a finally block is disallowed in %stry_finally_009.php on line %d

Zend/zend_opcode.c

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,24 @@ static void zend_extension_op_array_handler(zend_extension *extension, zend_op_a
485485
}
486486
}
487487

488+
static void zend_check_finally_breakout(zend_op_array *op_array, zend_op *opline, zend_uint dst_num TSRMLS_DC) {
489+
zend_uint i, op_num = opline - op_array->opcodes;
490+
for (i=0; i < op_array->last_try_catch; i++) {
491+
if (op_array->try_catch_array[i].try_op > op_num) {
492+
break;
493+
}
494+
if ((op_num >= op_array->try_catch_array[i].finally_op
495+
&& op_num < op_array->try_catch_array[i].finally_end)
496+
&& (dst_num >= op_array->try_catch_array[i].finally_end
497+
|| dst_num < op_array->try_catch_array[i].finally_op)) {
498+
CG(in_compilation) = 1;
499+
CG(active_op_array) = op_array;
500+
CG(zend_lineno) = opline->lineno;
501+
zend_error(E_COMPILE_ERROR, "jump out of a finally block is disallowed");
502+
}
503+
}
504+
}
505+
488506
ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
489507
{
490508
zend_op *opline, *end;
@@ -528,24 +546,30 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
528546
}
529547
/* break omitted intentionally */
530548
case ZEND_JMP:
549+
if (op_array->last_try_catch) {
550+
zend_check_finally_breakout(op_array, opline, opline->op1.opline_num TSRMLS_CC);
551+
}
552+
opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
553+
break;
554+
case ZEND_BRK:
555+
case ZEND_CONT:
531556
if (op_array->last_try_catch) {
532557
zend_uint i, op_num = opline - op_array->opcodes;
533-
for (i=0; i < op_array->last_try_catch; i++) {
534-
if (op_array->try_catch_array[i].try_op > op_num) {
535-
break;
558+
int nest_levels, array_offset;
559+
zend_brk_cont_element *jmp_to;
560+
561+
nest_levels = Z_LVAL_P(opline->op2.zv);
562+
array_offset = opline->op1.opline_num;
563+
do {
564+
jmp_to = &op_array->brk_cont_array[array_offset];
565+
if (nest_levels > 1) {
566+
array_offset = jmp_to->parent;
536567
}
537-
if ((op_num >= op_array->try_catch_array[i].finally_op
538-
&& op_num < op_array->try_catch_array[i].finally_end)
539-
&& (opline->op1.opline_num >= op_array->try_catch_array[i].finally_end
540-
|| opline->op1.opline_num < op_array->try_catch_array[i].finally_op)) {
541-
CG(in_compilation) = 1;
542-
CG(active_op_array) = op_array;
543-
CG(zend_lineno) = opline->lineno;
544-
zend_error(E_COMPILE_ERROR, "jump out of a finally block is disallowed");
545-
}
546-
}
568+
} while (--nest_levels > 0);
569+
if (op_array->last_try_catch) {
570+
zend_check_finally_breakout(op_array, opline, jmp_to->brk TSRMLS_CC);
571+
}
547572
}
548-
opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
549573
break;
550574
case ZEND_JMPZ:
551575
case ZEND_JMPNZ:

Zend/zend_vm_def.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5317,10 +5317,10 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)
53175317
ZEND_VM_NEXT_OPCODE();
53185318
}
53195319

5320-
ZEND_VM_HANDLER(159, ZEND_LEAVE, ANY, ANY) {
5321-
{
5320+
ZEND_VM_HANDLER(159, ZEND_LEAVE, ANY, ANY)
5321+
{
53225322
USE_OPLINE
5323-
zend_uint i, op_num = opline - EG(active_op_array)->opcodes;
5323+
zend_uint i, op_num = opline - EG(active_op_array)->opcodes;
53245324

53255325
SAVE_OPLINE();
53265326
zend_exception_restore(TSRMLS_C);

Zend/zend_vm_execute.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,9 +1176,9 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
11761176
}
11771177

11781178
static int ZEND_FASTCALL ZEND_LEAVE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
1179-
{
1179+
{
11801180
USE_OPLINE
1181-
zend_uint i, op_num = opline - EG(active_op_array)->opcodes;
1181+
zend_uint i, op_num = opline - EG(active_op_array)->opcodes;
11821182

11831183
SAVE_OPLINE();
11841184
zend_exception_restore(TSRMLS_C);

0 commit comments

Comments
 (0)