]> granicus.if.org Git - php/commitdiff
An exception thrown in try or catch block is disacarded by return statement in finall...
authorDmitry Stogov <dmitry@zend.com>
Wed, 12 Dec 2012 22:48:51 +0000 (02:48 +0400)
committerDmitry Stogov <dmitry@zend.com>
Wed, 12 Dec 2012 22:48:51 +0000 (02:48 +0400)
Zend/tests/catch_finally_006.phpt
Zend/tests/try_catch_finally_003.phpt
Zend/tests/try_finally_010.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_extensions.h
Zend/zend_modules.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_opcodes.h

index 9759eab37ef11571ec5051ab0065a1ace89fc750..216219b6a5b372c445afab1db4630bdbe57ee6ba 100644 (file)
@@ -25,4 +25,4 @@ try {
 --EXPECT--
 string(4) "para"
 string(7) "finally"
-string(2) "ex"
+string(6) "return"
index 784063b7490251f1e3bf2cdf62cd28c2d222784c..7ec8ec82db4d05385074eb4afb1f8c91f71f598a 100644 (file)
@@ -15,11 +15,9 @@ function foo () {
                 die("error");
             } finally {
                echo "1";
-               return 1;
             }
         } finally {
            echo "2";
-           return 2;
         }
     } catch (BE $e) {
       die("error");
diff --git a/Zend/tests/try_finally_010.phpt b/Zend/tests/try_finally_010.phpt
new file mode 100644 (file)
index 0000000..bbac8dd
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+Try finally (function call in the finaly block after exception)
+--FILE--
+<?php
+function foo() {
+       echo "4";
+}
+function bar() {
+       try {
+               echo "2";
+               throw new Exception();
+               echo "x";
+       } catch (MyEx $ex) {
+               echo "x";
+       } finally {
+               echo "3";
+               foo();
+               echo "5";
+       }
+}
+try {
+       echo "1";
+       bar();
+       echo "x";
+} catch (Exception $ex) {
+       echo "6";
+}
+echo "\n";
+--EXPECT--
+123456
index 3c7db272a955e7f345b82bc584be664cad5cec5d..ac3e633e28bfa48d6329a70c35c2b4afa23183b7 100644 (file)
@@ -181,6 +181,7 @@ void zend_init_compiler_context(TSRMLS_D) /* {{{ */
        CG(context).backpatch_count = 0;
        CG(context).nested_calls = 0;
        CG(context).used_stack = 0;
+       CG(context).in_finally = 0;
        CG(context).labels = NULL;
 }
 /* }}} */
@@ -287,7 +288,7 @@ ZEND_API zend_bool zend_is_compiling(TSRMLS_D) /* {{{ */
 
 static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */
 {
-       return EX_TMP_VAR_NUM(0, (op_array->T)++);
+       return (zend_uint)EX_TMP_VAR_NUM(0, (op_array->T)++);
 }
 /* }}} */
 
@@ -2671,6 +2672,13 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
                start_op_number++;
        }
 
+       if (CG(context).in_finally) {
+               opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+               opline->opcode = ZEND_DISCARD_EXCEPTION;
+               SET_UNUSED(opline->op1);
+               SET_UNUSED(opline->op2);
+       }
+       
        opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
        opline->opcode = returns_reference ? ZEND_RETURN_BY_REF : ZEND_RETURN;
@@ -2819,6 +2827,8 @@ void zend_do_finally(znode *finally_token TSRMLS_DC) /* {{{ */
        opline->opcode = ZEND_JMP;
        SET_UNUSED(opline->op1);
        SET_UNUSED(opline->op2);
+
+       CG(context).in_finally++;
 }
 /* }}} */
 
@@ -2897,6 +2907,8 @@ void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_to
                SET_UNUSED(opline->op2);
                
                CG(active_op_array)->opcodes[finally_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
+
+               CG(context).in_finally--;
        } 
 }
 /* }}} */
index da0a49bd511f5cde1b3023d62cfcd76b4b0dd0c5..c921c2a66fbc89c4ae6813da27da9ba4b4e6f030 100644 (file)
@@ -61,6 +61,7 @@ typedef struct _zend_compiler_context {
        int        backpatch_count;
        int        nested_calls;
        int        used_stack;
+       int        in_finally;
        HashTable *labels;
 } zend_compiler_context;
 
index 5be6be62a6b6689c842c51c961628b1102ecf912..3c609164c6f3c4fae0f5ca87205c8f6180f12d1e 100644 (file)
@@ -28,7 +28,7 @@
 /* The first number is the engine version and the rest is the date.
  * This way engine 2/3 API no. is always greater than engine 1 API no..
  */
-#define ZEND_EXTENSION_API_NO  220121204
+#define ZEND_EXTENSION_API_NO  220121212
 
 typedef struct _zend_extension_version_info {
        int zend_extension_api_no;
index b4ad648c795ee41cae07e411771eccdd967fde7c..a4ed106cfc665b3f5e0d032457c59fd6c946c451 100644 (file)
@@ -33,7 +33,7 @@
 #define ZEND_MODULE_INFO_FUNC_ARGS zend_module_entry *zend_module TSRMLS_DC
 #define ZEND_MODULE_INFO_FUNC_ARGS_PASSTHRU zend_module TSRMLS_CC
 
-#define ZEND_MODULE_API_NO 20121204
+#define ZEND_MODULE_API_NO 20121212
 #ifdef ZTS
 #define USING_ZTS 1
 #else
index 939dc1d066202be374ca84f6cf2a0869341af968..ef3f80e596aa84b50ead7855f739c01ef5b7072e 100644 (file)
@@ -1845,12 +1845,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
        zend_bool nested;
        zend_op_array *op_array = EX(op_array);
 
-       if (EXPECTED(EG(exception) == NULL) &&
-           UNEXPECTED(EG(prev_exception) != NULL)) {
-               /* return from finally block called because of unhandled exception */
-               zend_exception_restore(TSRMLS_C);               
-       }
-
        EG(current_execute_data) = EX(prev_execute_data);
        EG(opline_ptr) = NULL;
        if (!EG(active_symbol_table)) {
@@ -2960,12 +2954,6 @@ ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, ANY, ANY)
        /* The generator object is stored in return_value_ptr_ptr */
        zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
 
-       if (EXPECTED(EG(exception) == NULL) &&
-           UNEXPECTED(EG(prev_exception) != NULL)) {
-               /* return from finally block called because of unhandled exception */
-               zend_exception_restore(TSRMLS_C);               
-       }
-
        /* Close the generator to free up resources */
        zend_generator_close(generator, 1 TSRMLS_CC);
 
@@ -5409,6 +5397,17 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
        ZEND_VM_RETURN();
 }
 
+ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY)
+{
+       if (EG(prev_exception) != NULL) {
+               /* discard the previously thrown exception */
+               zval_ptr_dtor(&EG(prev_exception));
+               EG(prev_exception) = NULL;
+       }
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
 ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
 {
        USE_OPLINE
index dd77aa5f8ef1f3a0e2f684c126b1b1bdbf0782e1..4e4dedfd0888b3932e86c1f409609d127f6582eb 100644 (file)
@@ -386,12 +386,6 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
        zend_bool nested;
        zend_op_array *op_array = EX(op_array);
 
-       if (EXPECTED(EG(exception) == NULL) &&
-           UNEXPECTED(EG(prev_exception) != NULL)) {
-               /* return from finally block called because of unhandled exception */
-               zend_exception_restore(TSRMLS_C);
-       }
-
        EG(current_execute_data) = EX(prev_execute_data);
        EG(opline_ptr) = NULL;
        if (!EG(active_symbol_table)) {
@@ -696,12 +690,6 @@ static int ZEND_FASTCALL  ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER
        /* The generator object is stored in return_value_ptr_ptr */
        zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr);
 
-       if (EXPECTED(EG(exception) == NULL) &&
-           UNEXPECTED(EG(prev_exception) != NULL)) {
-               /* return from finally block called because of unhandled exception */
-               zend_exception_restore(TSRMLS_C);
-       }
-
        /* Close the generator to free up resources */
        zend_generator_close(generator, 1 TSRMLS_CC);
 
@@ -1134,6 +1122,17 @@ static int ZEND_FASTCALL  ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
        }
 }
 
+static int ZEND_FASTCALL  ZEND_DISCARD_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       if (EG(prev_exception) != NULL) {
+               /* discard the previously thrown exception */
+               zval_ptr_dtor(&EG(prev_exception));
+               EG(prev_exception) = NULL;
+       }
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
@@ -44827,31 +44826,31 @@ void zend_init_opcodes_handlers(void)
        ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
        ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
        ZEND_JMP_SET_VAR_SPEC_CV_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,
-       ZEND_NULL_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,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
-       ZEND_NULL_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
+       ZEND_DISCARD_EXCEPTION_SPEC_HANDLER,
        ZEND_YIELD_SPEC_CONST_CONST_HANDLER,
        ZEND_YIELD_SPEC_CONST_TMP_HANDLER,
        ZEND_YIELD_SPEC_CONST_VAR_HANDLER,
index 52f6cde59e71fc5a1c6a263a4f79c1e0c2213ca7..061d7e49b3a85f9c93b3d984f0318f3d97c604d3 100644 (file)
 #define ZEND_SEPARATE                        156
 #define ZEND_QM_ASSIGN_VAR                   157
 #define ZEND_JMP_SET_VAR                     158
+#define ZEND_DISCARD_EXCEPTION               159
 #define ZEND_YIELD                           160
 #define ZEND_GENERATOR_RETURN                161
 #define ZEND_FAST_CALL                       162