]> granicus.if.org Git - php/commitdiff
- Fixed bug #52060 (Memory leak when passing a closure to method_exists())
authorFelipe Pena <felipe@php.net>
Fri, 11 Jun 2010 23:20:13 +0000 (23:20 +0000)
committerFelipe Pena <felipe@php.net>
Fri, 11 Jun 2010 23:20:13 +0000 (23:20 +0000)
NEWS
Zend/tests/bug52060.phpt [new file with mode: 0644]
Zend/zend_builtin_functions.c

diff --git a/NEWS b/NEWS
index a9472addd392134aa4df37596d9baa1fcec1291d..2c16a43dbf5253a02c31cd2d66c6055c0e25d3cb 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -71,6 +71,8 @@ PHP                                                                        NEWS
   requests (Fixes CVE-2010-0397, bug #51288). (Raphael Geissert)
 - Fixed 64-bit integer overflow in mhash_keygen_s2k(). (ClĂ©ment LECIGNE, Stas)
 
+- Fixed bug #52060 (Memory leak when passing a closure to method_exists()).
+  (Felipe)
 - Fixed bug #52019 (make lcov doesn't support TESTS variable anymore). (Patrick)
 - Fixed bug #52010 (open_basedir restrictions mismatch on vacuum command).
   (Ilia)
diff --git a/Zend/tests/bug52060.phpt b/Zend/tests/bug52060.phpt
new file mode 100644 (file)
index 0000000..fef603b
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Bug #52060 (Memory leak when passing a closure to method_exists())
+--FILE--
+<?php
+
+$closure = function($a) { echo $a; };
+
+var_dump(method_exists($closure, '__invoke')); // true
+
+?>
+--EXPECT--
+bool(true)
index a56a823f7c4743c2b0480d996d8070847bb0ec07..06833ba97eb9c9536fc43c69f8f0fc47d63dc19a 100644 (file)
@@ -26,6 +26,7 @@
 #include "zend_ini.h"
 #include "zend_exceptions.h"
 #include "zend_extensions.h"
+#include "zend_closures.h"
 
 #undef ZEND_TEST_EXCEPTIONS
 
@@ -1098,22 +1099,29 @@ ZEND_FUNCTION(method_exists)
                RETURN_TRUE;
        } else {
                union _zend_function *func = NULL;
-               efree(lcname);
 
                if (Z_TYPE_P(klass) == IS_OBJECT 
                && Z_OBJ_HT_P(klass)->get_method != NULL
                && (func = Z_OBJ_HT_P(klass)->get_method(&klass, method_name, method_len TSRMLS_CC)) != NULL
                ) {
                        if (func->type == ZEND_INTERNAL_FUNCTION 
-                       && ((zend_internal_function*)func)->handler == zend_std_call_user_call
+                       && (func->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0
                        ) {
+                               /* Returns true to the fake Closure's __invoke */
+                               RETVAL_BOOL((func->common.scope == zend_ce_closure
+                                       && (method_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1)
+                                       && memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1) == 0) ? 1 : 0);
+
+                               efree(lcname);
                                efree(((zend_internal_function*)func)->function_name);
                                efree(func);
-                               RETURN_FALSE;
+                               return;
                        }
+                       efree(lcname);
                        RETURN_TRUE;
                }
        }
+       efree(lcname);
        RETURN_FALSE;
 }
 /* }}} */