]> granicus.if.org Git - php/commitdiff
Fixed bug #44184 (Double free of loop-variable on exception)
authorDmitry Stogov <dmitry@php.net>
Wed, 20 Feb 2008 12:06:29 +0000 (12:06 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 20 Feb 2008 12:06:29 +0000 (12:06 +0000)
Zend/tests/bug44184.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

diff --git a/Zend/tests/bug44184.phpt b/Zend/tests/bug44184.phpt
new file mode 100644 (file)
index 0000000..7f277ac
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+Bug #44184 (Double free of loop-variable on exception)
+--FILE--
+<?php
+function foo() {
+       $x = array(1,2,3);
+       foreach ($x as $a) {
+               while (1) {
+                       throw new Exception();
+               }
+           return;
+       }
+}
+try {
+       foo();
+} catch (Exception $ex) {
+       echo "ok\n";
+}
+?>
+--EXPECT--
+ok
index 625f28dcb8e0026e75602268c367c4a6abb940c7..db4f8837135c02307f6413b70ba8f761ee3df67d 100644 (file)
@@ -752,8 +752,14 @@ static inline void do_begin_loop(TSRMLS_D) /* {{{ */
 }
 /* }}} */
 
-static inline void do_end_loop(int cont_addr TSRMLS_DC) /* {{{ */
+static inline void do_end_loop(int cont_addr, int has_loop_var TSRMLS_DC) /* {{{ */
 {
+       if (!has_loop_var) {
+               /* The start fileld is used to free temporary variables in case of exceptions.
+                * We won't try to free something of we don't have loop variable.
+                */
+               CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].start = -1;
+       }
        CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = cont_addr;
        CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array));
        CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent;
@@ -788,7 +794,7 @@ void zend_do_while_end(znode *while_token, znode *close_bracket_token TSRMLS_DC)
        /* update while's conditional jmp */
        CG(active_op_array)->opcodes[close_bracket_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
 
-       do_end_loop(while_token->u.opline_num TSRMLS_CC);
+       do_end_loop(while_token->u.opline_num, 0 TSRMLS_CC);
 
        DEC_BPC(CG(active_op_array));
 }
@@ -832,7 +838,7 @@ void zend_do_for_end(znode *second_semicolon_token TSRMLS_DC) /* {{{ */
        SET_UNUSED(opline->op1);
        SET_UNUSED(opline->op2);
 
-       do_end_loop(second_semicolon_token->u.opline_num+1 TSRMLS_CC);
+       do_end_loop(second_semicolon_token->u.opline_num+1, 0 TSRMLS_CC);
 
        DEC_BPC(CG(active_op_array));
 }
@@ -3151,7 +3157,7 @@ void zend_do_do_while_end(znode *do_token, znode *expr_open_bracket, znode *expr
        opline->op2.u.opline_num = do_token->u.opline_num;
        SET_UNUSED(opline->op2);
 
-       do_end_loop(expr_open_bracket->u.opline_num TSRMLS_CC);
+       do_end_loop(expr_open_bracket->u.opline_num, 0 TSRMLS_CC);
 
        DEC_BPC(CG(active_op_array));
 }
@@ -4661,7 +4667,7 @@ void zend_do_foreach_end(znode *foreach_token, znode *as_token TSRMLS_DC) /* {{{
        CG(active_op_array)->opcodes[foreach_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); /* FE_RESET */
        CG(active_op_array)->opcodes[as_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); /* FE_FETCH */
 
-       do_end_loop(as_token->u.opline_num TSRMLS_CC);
+       do_end_loop(as_token->u.opline_num, 1 TSRMLS_CC);
 
        zend_stack_top(&CG(foreach_copy_stack), (void **) &container_ptr);
        generate_free_foreach_copy(container_ptr TSRMLS_CC);
index a8492af54c33df99b1514abd32e6b076a01c7bff..02f46bb61d58b4563ab9f614ff7b621f14158b30 100644 (file)
@@ -4219,11 +4219,12 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
        }
 
        for (i=0; i<EX(op_array)->last_brk_cont; i++) {
-               if (EX(op_array)->brk_cont_array[i].start > op_num) {
+               if (EX(op_array)->brk_cont_array[i].start < 0) {
+                       continue;
+               } else if (EX(op_array)->brk_cont_array[i].start > op_num) {
                        /* further blocks will not be relevant... */
                        break;
-               }
-               if (op_num < EX(op_array)->brk_cont_array[i].brk) {
+               } else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
                        if (!catched ||
                            catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
                                zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
index af489d9e6ed20e1b505af93b7094de69c97a270c..db6db39f637f6d8d73bbd6142ca3d1757d70f40c 100644 (file)
@@ -564,11 +564,12 @@ static int ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        }
 
        for (i=0; i<EX(op_array)->last_brk_cont; i++) {
-               if (EX(op_array)->brk_cont_array[i].start > op_num) {
+               if (EX(op_array)->brk_cont_array[i].start < 0) {
+                       continue;
+               } else if (EX(op_array)->brk_cont_array[i].start > op_num) {
                        /* further blocks will not be relevant... */
                        break;
-               }
-               if (op_num < EX(op_array)->brk_cont_array[i].brk) {
+               } else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
                        if (!catched ||
                            catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
                                zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];