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===
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php