]> granicus.if.org Git - php/commitdiff
Fix trampoline leak on dynamic static call of non-static method
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 22 Feb 2021 09:32:28 +0000 (10:32 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 22 Feb 2021 09:32:59 +0000 (10:32 +0100)
Fixes oss-fuzz #30317.

Zend/tests/dynamic_call_non_static.phpt [new file with mode: 0644]
Zend/zend_execute.c

diff --git a/Zend/tests/dynamic_call_non_static.phpt b/Zend/tests/dynamic_call_non_static.phpt
new file mode 100644 (file)
index 0000000..f73d29a
--- /dev/null
@@ -0,0 +1,30 @@
+--TEST--
+Dynamic static call of non-static method
+--FILE--
+<?php
+class Foo {
+    function test1() {
+        $method = ['Foo', 'bar'];
+        $method();
+    }
+    function test2() {
+        $method = 'Foo::bar';
+        $method();
+    }
+    function __call($name, $args) {}
+}
+$x = new Foo;
+try {
+    $x->test1();
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
+try {
+    $x->test2();
+} catch (Error $e) {
+    echo $e->getMessage(), "\n";
+}
+?>
+--EXPECT--
+Non-static method Foo::bar() cannot be called statically
+Non-static method Foo::bar() cannot be called statically
index edf6c61794168fd85957a7ae4c4fe99a2a9b6418..f6b2a6f9beab7555e117166bcc571cd84605ec18 100644 (file)
@@ -4005,6 +4005,10 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_string(zend_s
 
                if (UNEXPECTED(!(fbc->common.fn_flags & ZEND_ACC_STATIC))) {
                        zend_non_static_method_call(fbc);
+                       if (fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
+                               zend_string_release_ex(fbc->common.function_name, 0);
+                               zend_free_trampoline(fbc);
+                       }
                        return NULL;
                }
                if (EXPECTED(fbc->type == ZEND_USER_FUNCTION) && UNEXPECTED(!RUN_TIME_CACHE(&fbc->op_array))) {
@@ -4129,6 +4133,10 @@ static zend_never_inline zend_execute_data *zend_init_dynamic_call_array(zend_ar
                        }
                        if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
                                zend_non_static_method_call(fbc);
+                               if (fbc->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
+                                       zend_string_release_ex(fbc->common.function_name, 0);
+                                       zend_free_trampoline(fbc);
+                               }
                                return NULL;
                        }
                        object_or_called_scope = called_scope;