]> granicus.if.org Git - php/commitdiff
Fixed bug #75893
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 5 Feb 2018 20:41:44 +0000 (21:41 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 5 Feb 2018 20:41:44 +0000 (21:41 +0100)
It is not sufficient to just add the additional types for aliased
variables at the end of type inference, because types of derived
variables may depend on them. Make sure the additional types are
always added whenever the type of an aliased variable is updated.

NEWS
ext/opcache/Optimizer/zend_inference.c
ext/opcache/tests/bug75893.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 29349901610499f2d27121d7acbabc480d8b3421..ab1bc83346c6debe9787a289ab19ccdc0eca5760 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,8 @@ PHP                                                                        NEWS
 
 - Opcache:
   . Fixed bug #75729 (opcache segfault when installing Bitrix). (Nikita)
+  . Fixed bug #75893 (file_get_contents $http_response_header variable bugged
+    with opcache). (Nikita)
 
 - Standard:
   . Fixed bug #75916 (DNS_CAA record results contain garbage). (Mike,
index e5de5e60d70d801d5973cab3557f2f825ca14160..2601b60f3c78dea3367a2732b0c172acee2326d1 100644 (file)
@@ -1734,6 +1734,16 @@ static int zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{
 }
 /* }}} */
 
+static uint32_t get_ssa_alias_types(zend_ssa_alias_kind alias) {
+       if (alias == PHP_ERRORMSG_ALIAS) {
+               return MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN;
+       } else if (alias == HTTP_RESPONSE_HEADER_ALIAS) {
+               return MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_RC1 | MAY_BE_RCN;
+       } else {
+               return MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
+       }
+}
+
 #define UPDATE_SSA_TYPE(_type, _var)                                                                   \
        do {                                                                                                                            \
                uint32_t __type = (_type);                                                                              \
@@ -1742,7 +1752,8 @@ static int zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{
                        __type |= MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; \
                }                                                                                                                               \
                if (__var >= 0) {                                                                                               \
-                       if (ssa_vars[__var].var < op_array->last_var) {                         \
+                       zend_ssa_var *__ssa_var = &ssa_vars[__var];                                     \
+                       if (__ssa_var->var < op_array->last_var) {                                      \
                                if (__type & (MAY_BE_REF|MAY_BE_RCN)) {                                 \
                                        __type |= MAY_BE_RC1 | MAY_BE_RCN;                                      \
                                }                                                                                                               \
@@ -1750,6 +1761,9 @@ static int zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{
                                        /* TODO: support for array keys and ($str . "")*/   \
                                        __type |= MAY_BE_RCN;                               \
                                }                                                       \
+                               if (__ssa_var->alias) {                                                                 \
+                                       __type |= get_ssa_alias_types(__ssa_var->alias);        \
+                               }                                                                                                               \
                        }                                                                                                                       \
                        if (ssa_var_info[__var].type != __type) {                                       \
                                if (ssa_var_info[__var].type & ~__type) {                               \
@@ -3880,18 +3894,6 @@ static int zend_infer_types(const zend_op_array *op_array, const zend_script *sc
        /* Narrowing integer initialization to doubles */
        zend_type_narrowing(op_array, script, ssa);
 
-       for (j = 0; j < ssa_vars_count; j++) {
-               if (ssa->vars[j].alias) {
-                       if (ssa->vars[j].alias == PHP_ERRORMSG_ALIAS) {
-                               ssa_var_info[j].type |= MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN;
-                       } else if (ssa->vars[j].alias == HTTP_RESPONSE_HEADER_ALIAS) {
-                               ssa_var_info[j].type |= MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_RC1 | MAY_BE_RCN;
-                       } else {
-                               ssa_var_info[j].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
-                       }
-               }
-       }
-
        if (ZEND_FUNC_INFO(op_array)) {
                zend_func_return_info(op_array, script, 1, 0, &ZEND_FUNC_INFO(op_array)->return_info);
        }
@@ -3919,6 +3921,9 @@ int zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const
                for (i = 0; i < op_array->last_var; i++) {
                        ssa_var_info[i].type = MAY_BE_UNDEF;
                        ssa_var_info[i].has_range = 0;
+                       if (ssa->vars[i].alias) {
+                               ssa_var_info[i].type |= get_ssa_alias_types(ssa->vars[i].alias);
+                       }
                }
        }
        for (i = op_array->last_var; i < ssa->vars_count; i++) {
diff --git a/ext/opcache/tests/bug75893.phpt b/ext/opcache/tests/bug75893.phpt
new file mode 100644 (file)
index 0000000..670993c
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Bug #75893: file_get_contents $http_response_header variable bugged with opcache
+--INI--
+opcache.enable_cli=1
+track_errors=1
+--FILE--
+<?php
+
+function test() {
+    echo $undef;
+    $foo = $php_errormsg;
+    var_dump($foo[0]);
+}
+
+test();
+
+?>
+--EXPECTF--
+Deprecated: Directive 'track_errors' is deprecated in Unknown on line 0
+
+Notice: Undefined variable: undef in %s on line %d
+string(1) "U"