]> granicus.if.org Git - php/commitdiff
Fix DCE of throwing NEWs
authorNikita Popov <nikita.ppv@gmail.com>
Sat, 17 Feb 2018 13:50:20 +0000 (14:50 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Sat, 17 Feb 2018 13:51:11 +0000 (14:51 +0100)
ext/opcache/Optimizer/escape_analysis.c
ext/opcache/tests/invalid_new_dce.phpt [new file with mode: 0644]

index a1378721ab1bd3c19975c324bdf0df404fc5659b..66866e8b24b64468314c3d178c2b70e32a032e71 100644 (file)
@@ -177,9 +177,14 @@ static int is_allocation_def(zend_op_array *op_array, zend_ssa *ssa, int def, in
                            /* objects with destructors should escape */
                                if (opline->op1_type == IS_CONST) {
                                        zend_class_entry *ce = get_class_entry(script, Z_STR_P(CRT_CONSTANT_EX(op_array, opline, opline->op1, ssa->rt_constants)+1));
+                                       uint32_t forbidden_flags = ZEND_ACC_INHERITED
+                                               /* These flags will always cause an exception */
+                                               | ZEND_ACC_IMPLICIT_ABSTRACT_CLASS | ZEND_ACC_EXPLICIT_ABSTRACT_CLASS
+                                               | ZEND_ACC_INTERFACE | ZEND_ACC_TRAIT;
                                        if (ce && !ce->create_object && !ce->constructor &&
                                            !ce->destructor && !ce->__get && !ce->__set &&
-                                           !(ce->ce_flags & ZEND_ACC_INHERITED)) {
+                                           !(ce->ce_flags & forbidden_flags) &&
+                                               (ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
                                                return 1;
                                        }
                                }
diff --git a/ext/opcache/tests/invalid_new_dce.phpt b/ext/opcache/tests/invalid_new_dce.phpt
new file mode 100644 (file)
index 0000000..8f44b80
--- /dev/null
@@ -0,0 +1,40 @@
+--TEST--
+Throwings NEWs should not be DCEd
+--INI--
+opcache.enable_cli=1
+opcache.optimization_level=-1
+--FILE--
+<?php
+
+abstract class Foo {}
+interface Bar {}
+trait Baz {}
+
+class Abc {
+    const BAR = Abc::BAR;
+}
+
+function test1() {
+    $x = new Foo;
+}
+function test2() {
+    $x = new Bar;
+}
+function test3() {
+    $x = new Baz;
+}
+function test4() {
+    $x = new Abc;
+}
+
+try { test1(); } catch (Error $e) { echo $e->getMessage(), "\n"; }
+try { test2(); } catch (Error $e) { echo $e->getMessage(), "\n"; }
+try { test3(); } catch (Error $e) { echo $e->getMessage(), "\n"; }
+try { test4(); } catch (Error $e) { echo $e->getMessage(), "\n"; }
+
+?>
+--EXPECT--
+Cannot instantiate abstract class Foo
+Cannot instantiate interface Bar
+Cannot instantiate trait Baz
+Cannot declare self-referencing constant 'Abc::BAR'