]> granicus.if.org Git - php/commitdiff
Fixed bug #70207 (Finally is broken with opcache)
authorDmitry Stogov <dmitry@zend.com>
Mon, 10 Aug 2015 13:38:43 +0000 (16:38 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 10 Aug 2015 13:38:43 +0000 (16:38 +0300)
NEWS
ext/opcache/Optimizer/optimize_temp_vars_5.c
ext/opcache/tests/bug70207.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index a43b2a4399af63dfd1ed99902a76c03a799d7441..a29f54cbf04ca6fe38dd9b459c59e8611183e429 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,6 +5,7 @@ PHP                                                                        NEWS
 - Core:
   . Fixed bug #70223 (Incrementing value returned by magic getter). (Laruence)
   . Fixed bug #70215 (Segfault when __invoke is static). (Bob)
+  . Fixed bug #70207 (Finally is broken with opcache). (Laruence, Dmitry)
 
 - CLI server:
   . Fixed bug #66606 (Sets HTTP_CONTENT_TYPE but not CONTENT_TYPE).
index 0e96ee86242ee9365d5412884519bdc4ae5bcc04..172f9a1a62c6fa08bbc70731d218146614bf0ac7 100644 (file)
@@ -101,7 +101,37 @@ void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *c
                                }
                        } else {
                                if (!zend_bitset_in(valid_T, currT)) {
-                                       GET_AVAILABLE_T();
+                                       int use_new_var = 0;
+
+                                       /* Code in "finally" blocks may modify temorary variables.
+                                        * We allocate new temporaries for values that need to
+                                        * relive FAST_CALLs.
+                                        */
+                                       if ((op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) &&
+                                           (opline->opcode == ZEND_RETURN ||
+                                            opline->opcode == ZEND_RETURN_BY_REF ||
+                                            opline->opcode == ZEND_FREE ||
+                                            opline->opcode == ZEND_FE_FREE)) {
+                                               zend_op *curr = opline;
+
+                                               while (--curr >= end) {
+                                                       if (curr->opcode == ZEND_FAST_CALL) {
+                                                               use_new_var = 1;
+                                                               break;
+                                                       } else if (curr->opcode != ZEND_FREE &&
+                                                                  curr->opcode != ZEND_FE_FREE &&
+                                                                  curr->opcode != ZEND_VERIFY_RETURN_TYPE &&
+                                                                  curr->opcode != ZEND_DISCARD_EXCEPTION) {
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                                       if (use_new_var) {
+                                               i = ++max;
+                                               zend_bitset_incl(taken_T, i);
+                                       } else {
+                                               GET_AVAILABLE_T();
+                                       }
                                        map_T[currT] = i;
                                        zend_bitset_incl(valid_T, currT);
                                }
diff --git a/ext/opcache/tests/bug70207.phpt b/ext/opcache/tests/bug70207.phpt
new file mode 100644 (file)
index 0000000..c684ee6
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+Bug #70207 Finally is broken with opcache
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+opcache.file_update_protection=0
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+function bar() {
+       return "bar";
+}
+function foo() {
+    try { return bar(); }
+    finally { @fclose(null); }
+}
+
+var_dump(foo());
+?>
+--EXPECT--
+string(3) "bar"