diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | Zend/tests/bug65784.phpt | 60 | ||||
-rw-r--r-- | Zend/tests/finally_goto_001.phpt | 14 | ||||
-rw-r--r-- | Zend/tests/finally_goto_002.phpt | 14 | ||||
-rw-r--r-- | Zend/tests/finally_goto_003.phpt | 15 | ||||
-rw-r--r-- | Zend/tests/finally_goto_004.phpt | 14 | ||||
-rw-r--r-- | Zend/zend_compile.h | 1 | ||||
-rw-r--r-- | Zend/zend_execute.c | 1 | ||||
-rw-r--r-- | Zend/zend_opcode.c | 25 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 49 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 49 | ||||
-rw-r--r-- | ext/oci8/oci8.c | 4 | ||||
-rw-r--r-- | ext/oci8/package.xml | 23 | ||||
-rw-r--r-- | ext/oci8/php_oci8.h | 2 |
14 files changed, 228 insertions, 44 deletions
@@ -23,6 +23,7 @@ PHP NEWS emalloc/efree/estrdup (Anatol, Dmitry) . Implemented constant scalar expressions (with support for constants) (RFC: https://wiki.php.net/rfc/const_scalar_exprs). (Bob) + . Fixed bug #65784 (Segfault with finally). (Laruence, Dmitry) - cURL: . Implemented FR #65646 (re-enable CURLOPT_FOLLOWLOCATION with open_basedir diff --git a/Zend/tests/bug65784.phpt b/Zend/tests/bug65784.phpt new file mode 100644 index 0000000000..29f086b5e3 --- /dev/null +++ b/Zend/tests/bug65784.phpt @@ -0,0 +1,60 @@ +--TEST-- +Fixed Bug #65784 (Segfault with finally) +--FILE-- +<?php +function foo1() { + try { + throw new Exception("not catch"); + return true; + } finally { + try { + throw new Exception("catched"); + } catch (Exception $e) { + } + } +} +try { + $foo = foo1(); + var_dump($foo); +} catch (Exception $e) { + do { + var_dump($e->getMessage()); + } while ($e = $e->getPrevious()); +} + +function foo2() { + try { + try { + throw new Exception("catched"); + return true; + } finally { + try { + throw new Exception("catched"); + } catch (Exception $e) { + } + } + } catch (Exception $e) { + } +} + +$foo = foo2(); +var_dump($foo); + +function foo3() { + try { + throw new Exception("not catched"); + return true; + } finally { + try { + throw new NotExists(); + } catch (Exception $e) { + } + } +} + +$bar = foo3(); +--EXPECTF-- +string(9) "not catch" +NULL + +Fatal error: Class 'NotExists' not found in %sbug65784.php on line %d diff --git a/Zend/tests/finally_goto_001.phpt b/Zend/tests/finally_goto_001.phpt new file mode 100644 index 0000000000..990f78d4c7 --- /dev/null +++ b/Zend/tests/finally_goto_001.phpt @@ -0,0 +1,14 @@ +--TEST-- +jmp into a finally block 01 +--FILE-- +<?php +function foo() { + goto test; + try { + } finally { +test: + } +} +?> +--EXPECTF-- +Fatal error: jump into a finally block is disallowed in %sfinally_goto_001.php on line %d diff --git a/Zend/tests/finally_goto_002.phpt b/Zend/tests/finally_goto_002.phpt new file mode 100644 index 0000000000..a6bd9e307f --- /dev/null +++ b/Zend/tests/finally_goto_002.phpt @@ -0,0 +1,14 @@ +--TEST-- +jmp into a finally block 02 +--FILE-- +<?php +function foo() { + try { + goto test; + } finally { +test: + } +} +?> +--EXPECTF-- +Fatal error: jump into a finally block is disallowed in %sfinally_goto_002.php on line %d diff --git a/Zend/tests/finally_goto_003.phpt b/Zend/tests/finally_goto_003.phpt new file mode 100644 index 0000000000..8529ff7865 --- /dev/null +++ b/Zend/tests/finally_goto_003.phpt @@ -0,0 +1,15 @@ +--TEST-- +jmp into a finally block 03 +--FILE-- +<?php +function foo() { + try { + } finally { + goto test; +test: + } +} +echo "okey"; +?> +--EXPECTF-- +okey diff --git a/Zend/tests/finally_goto_004.phpt b/Zend/tests/finally_goto_004.phpt new file mode 100644 index 0000000000..d88ceedf52 --- /dev/null +++ b/Zend/tests/finally_goto_004.phpt @@ -0,0 +1,14 @@ +--TEST-- +jmp into a finally block 03 +--FILE-- +<?php +function foo() { + try { + } finally { +test: + } + goto test; +} +?> +--EXPECTF-- +Fatal error: jump into a finally block is disallowed in %sfinally_goto_004.php on line %d diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index e3f06a0012..5d89a2b5c0 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -401,6 +401,7 @@ struct _zend_execute_data { zend_class_entry *current_called_scope; zval *current_this; struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */ + zval *delayed_exception; call_slot *call_slots; call_slot *call; }; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 5aea39ea94..5c6d3e780b 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1650,6 +1650,7 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array EX(call) = NULL; EG(current_execute_data) = execute_data; EX(nested) = nested; + EX(delayed_exception) = NULL; if (!op_array->run_time_cache && op_array->last_cache_slot) { op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*)); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index ad08798884..ac16e81ef1 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -489,10 +489,15 @@ static void zend_check_finally_breakout(zend_op_array *op_array, zend_uint op_nu zend_uint i; 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 + 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_op && + dst_num <= op_array->try_catch_array[i].finally_end)) { + CG(in_compilation) = 1; + CG(active_op_array) = op_array; + CG(zend_lineno) = op_array->opcodes[op_num].lineno; + zend_error_noreturn(E_COMPILE_ERROR, "jump into a finally block is disallowed"); + } else 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)) { @@ -541,11 +546,11 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, while (i > 0) { i--; if (op_array->try_catch_array[i].finally_op && - op_num >= op_array->try_catch_array[i].try_op && - op_num < op_array->try_catch_array[i].finally_op - 1 && - (dst_num < op_array->try_catch_array[i].try_op || - dst_num > op_array->try_catch_array[i].finally_end)) { - + op_num >= op_array->try_catch_array[i].try_op && + op_num < op_array->try_catch_array[i].finally_op - 1 && + (dst_num < op_array->try_catch_array[i].try_op || + dst_num > op_array->try_catch_array[i].finally_end)) { + opline = get_next_op(op_array TSRMLS_CC); opline->opcode = ZEND_FAST_CALL; SET_UNUSED(opline->op1); @@ -565,7 +570,7 @@ static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, SET_UNUSED(opline->op2); opline->op1.opline_num = start_op; - break; + break; } } } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index f4224433ef..5385f3eec9 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5021,7 +5021,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) { zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes; int i; - zend_uint catch_op_num = 0, finally_op_num = 0; + zend_uint catch_op_num = 0, finally_op_num = 0, finally_op_end = 0; void **stack_frame; /* Figure out where the next stack frame (which maybe contains pushed @@ -5046,6 +5046,10 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) { finally_op_num = EX(op_array)->try_catch_array[i].finally_op; } + if (op_num >= EG(active_op_array)->try_catch_array[i].finally_op && + op_num < EG(active_op_array)->try_catch_array[i].finally_end) { + finally_op_end = EG(active_op_array)->try_catch_array[i].finally_end; + } } if (EX(call) >= EX(call_slots)) { @@ -5107,14 +5111,29 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) EX(old_error_reporting) = NULL; if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { - zend_exception_save(TSRMLS_C); + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + } + EX(delayed_exception) = EG(exception); + EG(exception) = NULL; EX(fast_ret) = NULL; ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } else if (catch_op_num) { + if (finally_op_end && catch_op_num > finally_op_end) { + /* we are going out of current finally scope */ + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + EX(delayed_exception) = NULL; + } + } ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]); ZEND_VM_CONTINUE(); } else { + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + EX(delayed_exception) = NULL; + } if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); } else { @@ -5405,10 +5424,10 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY) { - if (EG(prev_exception) != NULL) { + if (EX(delayed_exception) != NULL) { /* discard the previously thrown exception */ - zval_ptr_dtor(&EG(prev_exception)); - EG(prev_exception) = NULL; + zval_ptr_dtor(&EX(delayed_exception)); + EX(delayed_exception) = NULL; } ZEND_VM_NEXT_OPCODE(); @@ -5425,6 +5444,7 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY) ZEND_VM_CONTINUE(); } EX(fast_ret) = opline + 1; + EX(delayed_exception) = NULL; ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); ZEND_VM_CONTINUE(); } @@ -5441,16 +5461,17 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY) if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); - } else if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { - zend_exception_restore(TSRMLS_C); - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); - ZEND_VM_CONTINUE(); - } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { - zend_exception_restore(TSRMLS_C); - ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); } else { - zend_exception_restore(TSRMLS_C); - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + EG(exception) = EX(delayed_exception); + EX(delayed_exception) = NULL; + if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); + } else { + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + } } } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 77672a3d86..02f8acb6be 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1016,7 +1016,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER { zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes; int i; - zend_uint catch_op_num = 0, finally_op_num = 0; + zend_uint catch_op_num = 0, finally_op_num = 0, finally_op_end = 0; void **stack_frame; /* Figure out where the next stack frame (which maybe contains pushed @@ -1041,6 +1041,10 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) { finally_op_num = EX(op_array)->try_catch_array[i].finally_op; } + if (op_num >= EG(active_op_array)->try_catch_array[i].finally_op && + op_num < EG(active_op_array)->try_catch_array[i].finally_end) { + finally_op_end = EG(active_op_array)->try_catch_array[i].finally_end; + } } if (EX(call) >= EX(call_slots)) { @@ -1102,14 +1106,29 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER EX(old_error_reporting) = NULL; if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) { - zend_exception_save(TSRMLS_C); + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + } + EX(delayed_exception) = EG(exception); + EG(exception) = NULL; EX(fast_ret) = NULL; ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } else if (catch_op_num) { + if (finally_op_end && catch_op_num > finally_op_end) { + /* we are going out of current finally scope */ + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + EX(delayed_exception) = NULL; + } + } ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]); ZEND_VM_CONTINUE(); } else { + if (EX(delayed_exception)) { + zend_exception_set_previous(EG(exception), EX(delayed_exception) TSRMLS_CC); + EX(delayed_exception) = NULL; + } if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { @@ -1159,10 +1178,10 @@ 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) { + if (EX(delayed_exception) != NULL) { /* discard the previously thrown exception */ - zval_ptr_dtor(&EG(prev_exception)); - EG(prev_exception) = NULL; + zval_ptr_dtor(&EX(delayed_exception)); + EX(delayed_exception) = NULL; } ZEND_VM_NEXT_OPCODE(); @@ -1179,6 +1198,7 @@ static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) ZEND_VM_CONTINUE(); } EX(fast_ret) = opline + 1; + EX(delayed_exception) = NULL; ZEND_VM_SET_OPCODE(opline->op1.jmp_addr); ZEND_VM_CONTINUE(); } @@ -1195,16 +1215,17 @@ static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) { ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); - } else if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { - zend_exception_restore(TSRMLS_C); - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); - ZEND_VM_CONTINUE(); - } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { - zend_exception_restore(TSRMLS_C); - return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { - zend_exception_restore(TSRMLS_C); - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + EG(exception) = EX(delayed_exception); + EX(delayed_exception) = NULL; + if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) { + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); + ZEND_VM_CONTINUE(); + } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } } } diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c index f8abacf3e6..1e505f13e9 100644 --- a/ext/oci8/oci8.c +++ b/ext/oci8/oci8.c @@ -2201,6 +2201,9 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC) { sword errstatus; +#if (!((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2)))) + char version[256]; +#endif OCI_G(errcode) = 0; /* assume ping is successful */ @@ -2212,7 +2215,6 @@ static int php_oci_connection_ping(php_oci_connection *connection TSRMLS_DC) #if ((OCI_MAJOR_VERSION > 10) || ((OCI_MAJOR_VERSION == 10) && (OCI_MINOR_VERSION >= 2))) /* OCIPing available 10.2 onwards */ PHP_OCI_CALL_RETURN(errstatus, OCIPing, (connection->svc, OCI_G(err), OCI_DEFAULT)); #else - char version[256]; /* use good old OCIServerVersion() */ PHP_OCI_CALL_RETURN(errstatus, OCIServerVersion, (connection->svc, OCI_G(err), (text *)version, sizeof(version), OCI_HTYPE_SVCCTX)); #endif diff --git a/ext/oci8/package.xml b/ext/oci8/package.xml index 7be825b895..8e55b9abd5 100644 --- a/ext/oci8/package.xml +++ b/ext/oci8/package.xml @@ -49,8 +49,8 @@ libraries are available. <time>12:00:00</time> <version> - <release>2.0.6</release> - <api>2.0.6</api> + <release>2.0.7</release> + <api>2.0.7</api> </version> <stability> <release>stable</release> @@ -58,8 +58,7 @@ libraries are available. </stability> <license uri="http://www.php.net/license">PHP</license> <notes> -Added a LICENSE file to make it easier for PECL binary distributions -to conform with the license. + Build change: Fix source variable definition for C89 compatibility </notes> <contents> <dir name="/"> @@ -460,6 +459,22 @@ to conform with the license. <release> <version> + <release>2.0.6</release> + <api>2.0.6</api> + </version> + <stability> + <release>stable</release> + <api>stable</api> + </stability> + <license uri="http://www.php.net/license">PHP</license> + <notes> +Added a LICENSE file to make it easier for PECL binary distributions +to conform with the license. + </notes> +</release> + +<release> + <version> <release>2.0.5</release> <api>2.0.5</api> </version> diff --git a/ext/oci8/php_oci8.h b/ext/oci8/php_oci8.h index 7510415549..86c5abfa89 100644 --- a/ext/oci8/php_oci8.h +++ b/ext/oci8/php_oci8.h @@ -45,7 +45,7 @@ */ #undef PHP_OCI8_VERSION #endif -#define PHP_OCI8_VERSION "2.0.6" +#define PHP_OCI8_VERSION "2.0.7-dev" extern zend_module_entry oci8_module_entry; #define phpext_oci8_ptr &oci8_module_entry |