cseiler Tue Jun 30 17:14:38 2009 UTC Added files: (Branch: PHP_5_3) /php-src/ext/spl/tests spl_autoload_013.phpt spl_autoload_014.phpt
Modified files: /php-src NEWS /php-src/ext/spl php_spl.c /php-src/ext/spl/tests spl_autoload_bug48541.phpt Log: MFH: spl_autoload_unregister/spl_autoload_functions and closures
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.659&r2=1.2027.2.547.2.965.2.660&diff_format=u Index: php-src/NEWS diff -u php-src/NEWS:1.2027.2.547.2.965.2.659 php-src/NEWS:1.2027.2.547.2.965.2.660 --- php-src/NEWS:1.2027.2.547.2.965.2.659 Tue Jun 30 16:17:30 2009 +++ php-src/NEWS Tue Jun 30 17:14:37 2009 @@ -2,6 +2,9 @@ ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2009, PHP 5.3.1 +- Fixed spl_autoload_unregister/spl_autoad_functions wrt. Closures and + Functors. (Christian Seiler) + - Fixed bug #48681 (openssl signature verification for tar archives broken). (Greg) - Fixed bug #47351 (Memory leak in DateTime). (Derick, Tobias John) http://cvs.php.net/viewvc.cgi/php-src/ext/spl/php_spl.c?r1=1.52.2.28.2.17.2.38&r2=1.52.2.28.2.17.2.39&diff_format=u Index: php-src/ext/spl/php_spl.c diff -u php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.38 php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.39 --- php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.38 Sat Jun 13 17:30:50 2009 +++ php-src/ext/spl/php_spl.c Tue Jun 30 17:14:37 2009 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_spl.c,v 1.52.2.28.2.17.2.38 2009/06/13 17:30:50 cellog Exp $ */ +/* $Id: php_spl.c,v 1.52.2.28.2.17.2.39 2009/06/30 17:14:37 cseiler Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -509,10 +509,10 @@ alfi.closure = zcallable; Z_ADDREF_P(zcallable); - lc_name = erealloc(lc_name, func_name_len + 2 + sizeof(zcallable->value.obj.handle)); - memcpy(lc_name + func_name_len, &(zcallable->value.obj.handle), - sizeof(zcallable->value.obj.handle)); - func_name_len += sizeof(zcallable->value.obj.handle); + lc_name = erealloc(lc_name, func_name_len + 2 + sizeof(zend_object_handle)); + memcpy(lc_name + func_name_len, &Z_OBJ_HANDLE_P(zcallable), + sizeof(zend_object_handle)); + func_name_len += sizeof(zend_object_handle); lc_name[func_name_len] = '\0'; } @@ -579,6 +579,7 @@ { char *func_name, *error = NULL; int func_name_len; + char *lc_name = NULL; zval *zcallable; int success = FAILURE; zend_function *spl_func_ptr; @@ -604,10 +605,20 @@ efree(error); } - zend_str_tolower(func_name, func_name_len); + lc_name = safe_emalloc(func_name_len, 1, sizeof(long) + 1); + zend_str_tolower_copy(lc_name, func_name, func_name_len); + efree(func_name); + + if (Z_TYPE_P(zcallable) == IS_OBJECT) { + lc_name = erealloc(lc_name, func_name_len + 2 + sizeof(zend_object_handle)); + memcpy(lc_name + func_name_len, &Z_OBJ_HANDLE_P(zcallable), + sizeof(zend_object_handle)); + func_name_len += sizeof(zend_object_handle); + lc_name[func_name_len] = '\0'; + } if (SPL_G(autoload_functions)) { - if (func_name_len == sizeof("spl_autoload_call")-1 && !strcmp(func_name, "spl_autoload_call")) { + if (func_name_len == sizeof("spl_autoload_call")-1 && !strcmp(lc_name, "spl_autoload_call")) { /* remove all */ zend_hash_destroy(SPL_G(autoload_functions)); FREE_HASHTABLE(SPL_G(autoload_functions)); @@ -616,16 +627,16 @@ success = SUCCESS; } else { /* remove specific */ - success = zend_hash_del(SPL_G(autoload_functions), func_name, func_name_len+1); + success = zend_hash_del(SPL_G(autoload_functions), lc_name, func_name_len+1); if (success != SUCCESS && obj_ptr) { - func_name = erealloc(func_name, func_name_len + 1 + sizeof(zend_object_handle)); - memcpy(func_name + func_name_len, &Z_OBJ_HANDLE_P(obj_ptr), sizeof(zend_object_handle)); + lc_name = erealloc(lc_name, func_name_len + 2 + sizeof(zend_object_handle)); + memcpy(lc_name + func_name_len, &Z_OBJ_HANDLE_P(obj_ptr), sizeof(zend_object_handle)); func_name_len += sizeof(zend_object_handle); - func_name[func_name_len] = '\0'; - success = zend_hash_del(SPL_G(autoload_functions), func_name, func_name_len+1); + lc_name[func_name_len] = '\0'; + success = zend_hash_del(SPL_G(autoload_functions), lc_name, func_name_len+1); } } - } else if (func_name_len == sizeof("spl_autoload")-1 && !strcmp(func_name, "spl_autoload")) { + } else if (func_name_len == sizeof("spl_autoload")-1 && !strcmp(lc_name, "spl_autoload")) { /* register single spl_autoload() */ zend_hash_find(EG(function_table), "spl_autoload", sizeof("spl_autoload"), (void **) &spl_func_ptr); @@ -635,7 +646,7 @@ } } - efree(func_name); + efree(lc_name); RETURN_BOOL(success == SUCCESS); } /* }}} */ @@ -663,7 +674,10 @@ zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), &function_pos); while(zend_hash_has_more_elements_ex(SPL_G(autoload_functions), &function_pos) == SUCCESS) { zend_hash_get_current_data_ex(SPL_G(autoload_functions), (void **) &alfi, &function_pos); - if (alfi->func_ptr->common.scope) { + if (alfi->closure) { + Z_ADDREF_P(alfi->closure); + add_next_index_zval(return_value, alfi->closure); + } else if (alfi->func_ptr->common.scope) { zval *tmp; MAKE_STD_ZVAL(tmp); array_init(tmp); http://cvs.php.net/viewvc.cgi/php-src/ext/spl/tests/spl_autoload_bug48541.phpt?r1=1.1.2.2&r2=1.1.2.3&diff_format=u Index: php-src/ext/spl/tests/spl_autoload_bug48541.phpt diff -u php-src/ext/spl/tests/spl_autoload_bug48541.phpt:1.1.2.2 php-src/ext/spl/tests/spl_autoload_bug48541.phpt:1.1.2.3 --- php-src/ext/spl/tests/spl_autoload_bug48541.phpt:1.1.2.2 Sat Jun 13 17:30:50 2009 +++ php-src/ext/spl/tests/spl_autoload_bug48541.phpt Tue Jun 30 17:14:37 2009 @@ -2,23 +2,38 @@ SPL: spl_autoload_register() Bug #48541: registering multiple closures fails with memleaks --FILE-- <?php + +class X { + public function getClosure() { + return function($class) { + echo "a2 called\n"; + }; + } +} + $a = function ($class) { echo "a called\n"; }; +$x = new X; +$a2 = $x->getClosure(); $b = function ($class) { eval('class ' . $class . '{function __construct(){echo "foo\n";}}'); echo "b called\n"; }; spl_autoload_register($a); +spl_autoload_register($a2); spl_autoload_register($b); $c = $a; +$c2 = $a2; spl_autoload_register($c); +spl_autoload_register($c2); $c = new foo; ?> ===DONE=== --EXPECT-- a called +a2 called b called foo ===DONE=== \ No newline at end of file http://cvs.php.net/viewvc.cgi/php-src/ext/spl/tests/spl_autoload_013.phpt?view=markup&rev=1.1 Index: php-src/ext/spl/tests/spl_autoload_013.phpt +++ php-src/ext/spl/tests/spl_autoload_013.phpt --TEST-- SPL: spl_autoload_functions() with closures and invokables --FILE-- <?php $closure = function($class) { echo "a called\n"; }; class Autoloader { private $dir; public function __construct($dir) { $this->dir = $dir; } public function __invoke($class) { var_dump("{$this->dir}/$class.php"); } } $al1 = new Autoloader('d1'); $al2 = new Autoloader('d2'); spl_autoload_register($closure); spl_autoload_register($al1); spl_autoload_register($al2); var_dump(spl_autoload_functions()); ?> ===DONE=== --EXPECTF-- array(3) { [0]=> object(Closure)#%d (2) { ["this"]=> NULL ["parameter"]=> array(1) { ["$class"]=> string(10) "<required>" } } [1]=> object(Autoloader)#%d (1) { [u"dir":u"Autoloader":private]=> unicode(2) "d1" } [2]=> object(Autoloader)#%d (1) { [u"dir":u"Autoloader":private]=> unicode(2) "d2" } } ===DONE=== http://cvs.php.net/viewvc.cgi/php-src/ext/spl/tests/spl_autoload_014.phpt?view=markup&rev=1.1 Index: php-src/ext/spl/tests/spl_autoload_014.phpt +++ php-src/ext/spl/tests/spl_autoload_014.phpt --TEST-- SPL: spl_autoload_unregister() with closures and invokables --FILE-- <?php $closure = function($class) { echo "closure called with class $class\n"; }; class Autoloader { private $dir; public function __construct($dir) { $this->dir = $dir; } public function __invoke($class) { echo ("Autoloader('{$this->dir}') called with $class\n"); } } class WorkingAutoloader { public function __invoke($class) { echo ("WorkingAutoloader() called with $class\n"); eval("class $class { }"); } } $al1 = new Autoloader('d1'); $al2 = new WorkingAutoloader('d2'); spl_autoload_register($closure); spl_autoload_register($al1); spl_autoload_register($al2); $x = new TestX; spl_autoload_unregister($closure); spl_autoload_unregister($al1); $y = new TestY; ?> ===DONE=== --EXPECT-- closure called with class TestX Autoloader('d1') called with TestX WorkingAutoloader() called with TestX WorkingAutoloader() called with TestY ===DONE===
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php