summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/tests/is_callable_trampoline_uaf.phpt27
-rw-r--r--Zend/zend_API.c7
-rw-r--r--Zend/zend_execute_API.c1
3 files changed, 29 insertions, 6 deletions
diff --git a/Zend/tests/is_callable_trampoline_uaf.phpt b/Zend/tests/is_callable_trampoline_uaf.phpt
new file mode 100644
index 0000000000..2410864410
--- /dev/null
+++ b/Zend/tests/is_callable_trampoline_uaf.phpt
@@ -0,0 +1,27 @@
+--TEST--
+is_callable() with trampoline should not caused UAF
+--FILE--
+<?php
+
+class B {}
+class A extends B {
+ public function bar($func) {
+ var_dump(is_callable(array('parent', 'foo')));
+ }
+
+ public function __call($func, $args) {
+ }
+}
+
+class X {
+ public static function __callStatic($func, $args) {
+ }
+}
+
+$a = new A();
+// Extra X::foo() wrapper to force use of allocated trampoline.
+X::foo($a->bar('foo'));
+
+?>
+--EXPECT--
+bool(false)
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 8ca81fc7d0..f826af856d 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -2963,12 +2963,7 @@ get_function_via_handler:
if (strict_class &&
(!fcc->function_handler->common.scope ||
!instanceof_function(ce_org, fcc->function_handler->common.scope))) {
- if (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
- if (fcc->function_handler->common.function_name) {
- zend_string_release_ex(fcc->function_handler->common.function_name, 0);
- }
- zend_free_trampoline(fcc->function_handler);
- }
+ zend_release_fcall_info_cache(fcc);
} else {
retval = 1;
call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index a1bae5ea3a..e2410cf6af 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -173,6 +173,7 @@ void init_executor(void) /* {{{ */
EG(prev_exception) = NULL;
EG(fake_scope) = NULL;
+ EG(trampoline).common.function_name = NULL;
EG(ht_iterators_count) = sizeof(EG(ht_iterators_slots)) / sizeof(HashTableIterator);
EG(ht_iterators_used) = 0;