cvs: php-src /ext/spl php_spl.c /ext/spl/tests spl_autoload_013.phpt spl_autoload_014.phpt spl_autoload_bug48541.phpt

From: Date: Mon, 22 Jun 2009 18:14:14 +0000
Subject: cvs: php-src /ext/spl php_spl.c /ext/spl/tests spl_autoload_013.phpt spl_autoload_014.phpt spl_autoload_bug48541.phpt
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-58900@lists.php.net to get a copy of this message
cseiler Mon Jun 22 18:14:14 2009 UTC Added files: /php-src/ext/spl/tests spl_autoload_013.phpt spl_autoload_014.phpt Modified files: /php-src/ext/spl php_spl.c /php-src/ext/spl/tests spl_autoload_bug48541.phpt Log: - Fixed spl_autoload_functions/spl_autoload_unregister wrt. closures and invokables.

http://cvs.php.net/viewvc.cgi/php-src/ext/spl/php_spl.c?r1=1.159&r2=1.160&diff_format=u Index: php-src/ext/spl/php_spl.c diff -u php-src/ext/spl/php_spl.c:1.159 php-src/ext/spl/php_spl.c:1.160 --- php-src/ext/spl/php_spl.c:1.159 Sat Jun 13 17:28:35 2009 +++ php-src/ext/spl/php_spl.c Mon Jun 22 18:14:14 2009 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_spl.c,v 1.159 2009/06/13 17:28:35 cellog Exp $ */ +/* $Id: php_spl.c,v 1.160 2009/06/22 18:14:14 cseiler Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -502,6 +502,9 @@ alfi.ce = fcc.calling_scope; alfi.func_ptr = fcc.function_handler; obj_ptr = fcc.object_ptr; + + zend_u_str_tolower(Z_TYPE(zfunc_name), Z_UNIVAL(zfunc_name), Z_UNILEN(zfunc_name)); + if (Z_TYPE_P(zcallable) == IS_OBJECT) { zstr lc_name; @@ -510,9 +513,9 @@ alfi.closure = zcallable; Z_ADDREF_P(zcallable); - lc_name.v = Z_UNIVAL(zfunc_name).v = erealloc(Z_UNIVAL(zfunc_name).v, func_name_len + 2 + sizeof(zcallable->value.obj.handle)); - memcpy(lc_name.s + func_name_len, &(zcallable->value.obj.handle), sizeof(zcallable->value.obj.handle)); - func_name_len += sizeof(zcallable->value.obj.handle); + lc_name.v = Z_UNIVAL(zfunc_name).v = erealloc(Z_UNIVAL(zfunc_name).v, func_name_len + 2 + sizeof(zend_object_handle)); + memcpy(lc_name.s + func_name_len, &Z_OBJ_HANDLE_P(zcallable), sizeof(zend_object_handle)); + func_name_len += sizeof(zend_object_handle); if (Z_TYPE(zfunc_name) == IS_UNICODE) { func_name_len /= sizeof(UChar); Z_STRLEN(zfunc_name) = func_name_len; @@ -526,7 +529,6 @@ efree(error); } - zend_u_str_tolower(Z_TYPE(zfunc_name), Z_UNIVAL(zfunc_name), Z_UNILEN(zfunc_name)); if (SPL_G(autoload_functions) && zend_u_hash_exists(SPL_G(autoload_functions), Z_TYPE(zfunc_name), Z_UNIVAL(zfunc_name), Z_UNILEN(zfunc_name)+1)) { if (alfi.closure) { Z_DELREF_P(zcallable); @@ -601,6 +603,7 @@ zval zfunc_name; zval *zcallable; zstr lc_name; + size_t lc_name_len; int success = FAILURE; zend_function *spl_func_ptr; zval *obj_ptr; @@ -624,10 +627,24 @@ } lc_name = zend_u_str_tolower_dup(Z_TYPE(zfunc_name), Z_UNIVAL(zfunc_name), Z_UNILEN(zfunc_name)); + lc_name_len = Z_UNILEN(zfunc_name); + + if (Z_TYPE_P(zcallable) == IS_OBJECT) { + lc_name_len = Z_UNISIZE(zfunc_name); + lc_name.v = erealloc(lc_name.v, lc_name_len + 2 + sizeof(zend_object_handle)); + memcpy(lc_name.s + lc_name_len, &Z_OBJ_HANDLE_P(zcallable), sizeof(zend_object_handle)); + lc_name_len += sizeof(zend_object_handle); + if (Z_TYPE(zfunc_name) == IS_UNICODE) { + lc_name_len /= sizeof(UChar); + lc_name.u[lc_name_len] = 0; + } else { + lc_name.s[lc_name_len] = '\0'; + } + } if (SPL_G(autoload_functions)) { - if ((Z_UNILEN(zfunc_name) == sizeof("spl_autoload_call")-1) && - (ZEND_U_EQUAL(Z_TYPE(zfunc_name), lc_name, Z_UNILEN(zfunc_name), "spl_autoload_call", sizeof("spl_autoload_call")-1))) { + if ((lc_name_len == sizeof("spl_autoload_call")-1) && + (ZEND_U_EQUAL(Z_TYPE(zfunc_name), lc_name, lc_name_len, "spl_autoload_call", sizeof("spl_autoload_call")-1))) { /* remove all */ zend_hash_destroy(SPL_G(autoload_functions)); FREE_HASHTABLE(SPL_G(autoload_functions)); @@ -636,23 +653,25 @@ success = SUCCESS; } else { /* remove specific */ - success = zend_u_hash_del(SPL_G(autoload_functions), Z_TYPE(zfunc_name), lc_name, Z_UNILEN(zfunc_name)+1); + success = zend_u_hash_del(SPL_G(autoload_functions), Z_TYPE(zfunc_name), lc_name, lc_name_len+1); if (success != SUCCESS && obj_ptr) { - size_t func_name_len = Z_UNISIZE(zfunc_name); - lc_name.v = erealloc(lc_name.v, func_name_len + 2 + sizeof(zend_object_handle)); - memcpy(lc_name.s + func_name_len, &Z_OBJ_HANDLE_P(obj_ptr), sizeof(zend_object_handle)); - func_name_len += sizeof(zend_object_handle); if (Z_TYPE(zfunc_name) == IS_UNICODE) { - func_name_len /= sizeof(UChar); - lc_name.u[func_name_len] = 0; + lc_name_len *= sizeof(UChar); + } + lc_name.v = erealloc(lc_name.v, lc_name_len + 2 + sizeof(zend_object_handle)); + memcpy(lc_name.s + lc_name_len, &Z_OBJ_HANDLE_P(obj_ptr), sizeof(zend_object_handle)); + lc_name_len += sizeof(zend_object_handle); + if (Z_TYPE(zfunc_name) == IS_UNICODE) { + lc_name_len /= sizeof(UChar); + lc_name.u[lc_name_len] = 0; } else { - lc_name.s[func_name_len] = '\0'; + lc_name.s[lc_name_len] = '\0'; } - success = zend_u_hash_del(SPL_G(autoload_functions), Z_TYPE(zfunc_name), lc_name, func_name_len+1); + success = zend_u_hash_del(SPL_G(autoload_functions), Z_TYPE(zfunc_name), lc_name, lc_name_len+1); } } - } else if ((Z_UNILEN(zfunc_name) == sizeof("spl_autoload")-1) && - (ZEND_U_EQUAL(Z_TYPE(zfunc_name), lc_name, Z_UNILEN(zfunc_name), "spl_autoload", sizeof("spl_autoload")-1))) { + } else if ((lc_name_len == sizeof("spl_autoload")-1) && + (ZEND_U_EQUAL(Z_TYPE(zfunc_name), lc_name, lc_name_len, "spl_autoload", sizeof("spl_autoload")-1))) { /* register single spl_autoload() */ zend_hash_find(EG(function_table), "spl_autoload", sizeof("spl_autoload"), (void **) &spl_func_ptr); @@ -692,7 +711,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&r2=1.2&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 php-src/ext/spl/tests/spl_autoload_bug48541.phpt:1.2 --- php-src/ext/spl/tests/spl_autoload_bug48541.phpt:1.1 Sat Jun 13 17:28:35 2009 +++ php-src/ext/spl/tests/spl_autoload_bug48541.phpt Mon Jun 22 18:14:14 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===
« previous php.cvs (#58900) next »