]> granicus.if.org Git - php/commitdiff
Prevent inlining through call_user_func() and call_user_func_array()
authorDmitry Stogov <dmitry@zend.com>
Thu, 30 Jun 2016 21:16:54 +0000 (00:16 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 30 Jun 2016 21:16:54 +0000 (00:16 +0300)
ext/opcache/Optimizer/optimize_func_calls.c
ext/opcache/tests/wrong_inlining_004.phpt [new file with mode: 0644]

index 1a0c0fd9b140b4a7e9a08283ec95550ac8af3aae..f98149a09ebda4ff9655545a1eba20373fdccc67 100644 (file)
@@ -39,6 +39,7 @@
 typedef struct _optimizer_call_info {
        zend_function *func;
        zend_op       *opline;
+       zend_bool      try_inline;
 } optimizer_call_info;
 
 static void zend_delete_call_instructions(zend_op *opline)
@@ -159,6 +160,7 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
                        case ZEND_INIT_FCALL:
                                call_stack[call].func = zend_optimizer_get_called_func(
                                        ctx->script, op_array, opline, 0);
+                               call_stack[call].try_inline = 1;
                                /* break missing intentionally */
                        case ZEND_NEW:
                        case ZEND_INIT_DYNAMIC_CALL:
@@ -198,12 +200,14 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
                                                ZEND_ASSERT(0);
                                        }
 
-                                       if (ZEND_OPTIMIZER_PASS_16 & ctx->optimization_level) {
+                                       if ((ZEND_OPTIMIZER_PASS_16 & ctx->optimization_level)
+                                        && call_stack[call].try_inline) {
                                                zend_try_inline_call(op_array, fcall, opline, call_stack[call].func);
                                        }
                                }
                                call_stack[call].func = NULL;
                                call_stack[call].opline = NULL;
+                               call_stack[call].try_inline = 0;
                                break;
                        case ZEND_FETCH_FUNC_ARG:
                        case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
@@ -257,17 +261,10 @@ void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
                                        }
                                }
                                break;
-#if 0
-                       case ZEND_SEND_REF:
-                               if (call_stack[call - 1].func) {
-                                       /* We won't handle run-time pass by reference */
-                                       call_stack[call - 1].opline = NULL;
-                               }
-                               break;
-#endif
                        case ZEND_SEND_UNPACK:
-                               call_stack[call - 1].func = NULL;
-                               call_stack[call - 1].opline = NULL;
+                       case ZEND_SEND_USER:
+                       case ZEND_SEND_ARRAY:
+                               call_stack[call - 1].try_inline = 0;
                                break;
                        default:
                                break;
diff --git a/ext/opcache/tests/wrong_inlining_004.phpt b/ext/opcache/tests/wrong_inlining_004.phpt
new file mode 100644 (file)
index 0000000..d4b2d39
--- /dev/null
@@ -0,0 +1,23 @@
+--TEST--
+Inlining throgh call_user_func()
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.optimization_level=-1
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+function get_const() {
+    return 42;
+}
+
+function test() {
+    $x = new stdClass;
+    var_dump(call_user_func('get_const', $x));
+}
+
+test();
+?>
+--EXPECTF--
+int(42)