]> granicus.if.org Git - php/commitdiff
Fixed bug #77266 (Assertion failed in dce_live_ranges)
authorXinchen Hui <laruence@gmail.com>
Tue, 8 Jan 2019 11:17:46 +0000 (19:17 +0800)
committerXinchen Hui <laruence@gmail.com>
Tue, 8 Jan 2019 11:19:01 +0000 (19:19 +0800)
NEWS
ext/opcache/Optimizer/zend_optimizer.c
ext/opcache/tests/bug77266.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 050c222fcabc95650997bf24c621b0aff7ec2f8d..48566bb35760f07a7219a1ee9957dd68756f5bf3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -43,6 +43,7 @@ PHP                                                                        NEWS
       no external visibility). (Anatol)
 
 - Opcache:
+  . Fixed bug #77266 (Assertion failed in dce_live_ranges). (Laruence)
   . Fixed bug #77257 (value of variable assigned in a switch() construct gets
     lost). (Nikita)
 
index 5d34525af91e509a68385617c499db37ef7de671..cb6cdf61d9d027be859a4180f29b3e47f8f0d031 100644 (file)
@@ -621,6 +621,39 @@ void zend_optimizer_remove_live_range(zend_op_array *op_array, uint32_t var)
        }
 }
 
+static uint32_t zend_determine_constructor_call(zend_op_array *op_array, uint32_t start) {
+       int call = 0;
+       while (start++ < op_array->last) {
+               switch (op_array->opcodes[start].opcode) {
+                       case ZEND_INIT_FCALL_BY_NAME:
+                       case ZEND_INIT_NS_FCALL_BY_NAME:
+                       case ZEND_INIT_STATIC_METHOD_CALL:
+                       case ZEND_INIT_METHOD_CALL:
+                       case ZEND_INIT_FCALL:
+                       case ZEND_NEW:
+                       case ZEND_INIT_DYNAMIC_CALL:
+                       case ZEND_INIT_USER_CALL:
+                               call++;
+                               break;
+                       case ZEND_DO_FCALL:
+                               if (call == 0) {
+                                       return start;
+                               }
+                       /* break missing intentionally */
+                       case ZEND_DO_ICALL:
+                       case ZEND_DO_UCALL:
+                       case ZEND_DO_FCALL_BY_NAME:
+                               call--;
+                               break;
+                       default:
+                               break;
+               }
+       }
+
+       ZEND_ASSERT(0);
+       return -1;
+}
+
 void zend_optimizer_remove_live_range_ex(zend_op_array *op_array, uint32_t var, uint32_t start)
 {
        uint32_t i = 0;
@@ -638,7 +671,12 @@ void zend_optimizer_remove_live_range_ex(zend_op_array *op_array, uint32_t var,
                case ZEND_FE_RESET_R:
                case ZEND_FE_RESET_RW:
                        var |= ZEND_LIVE_LOOP;
-                       /* break missing intentionally */
+                       start++;
+                       break;
+               case ZEND_NEW:
+                       start = zend_determine_constructor_call(op_array, start);
+                       start++;
+                       break;
                default:
                        start++;
        }
diff --git a/ext/opcache/tests/bug77266.phpt b/ext/opcache/tests/bug77266.phpt
new file mode 100644 (file)
index 0000000..8e225b8
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Bug #77266 (Assertion failed in dce_live_ranges)
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+final class Lock
+{
+       private static function clearOrphanedLocks()
+       {
+               $lockList = [];
+
+               $serverMonitors = array();
+               $listCount = count($lockList);
+               if ( is_array($lockList) && $listCount > 0 ) {
+                       $v = explode(':', $value);
+                       if (!$serverMonitors[$v[0]]['m']) {
+                               $serverMonitors[$v[0]]['m'] = new ServerMonitor($v[0]);
+                       }
+
+               }
+
+       }
+
+}
+?>
+okey
+--EXPECT--
+okey