mirror of
https://github.com/php/php-src.git
synced 2024-11-29 12:53:37 +08:00
MFH: spl_autoload_unregister/spl_autoload_functions and closures
This commit is contained in:
parent
9dfb40ea8c
commit
b4a43d0d94
3
NEWS
3
NEWS
@ -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)
|
||||
|
@ -509,10 +509,10 @@ PHP_FUNCTION(spl_autoload_register)
|
||||
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 @@ PHP_FUNCTION(spl_autoload_unregister)
|
||||
{
|
||||
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 @@ PHP_FUNCTION(spl_autoload_unregister)
|
||||
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 @@ PHP_FUNCTION(spl_autoload_unregister)
|
||||
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 @@ PHP_FUNCTION(spl_autoload_unregister)
|
||||
}
|
||||
}
|
||||
|
||||
efree(func_name);
|
||||
efree(lc_name);
|
||||
RETURN_BOOL(success == SUCCESS);
|
||||
} /* }}} */
|
||||
|
||||
@ -663,7 +674,10 @@ PHP_FUNCTION(spl_autoload_functions)
|
||||
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);
|
||||
|
51
ext/spl/tests/spl_autoload_013.phpt
Normal file
51
ext/spl/tests/spl_autoload_013.phpt
Normal file
@ -0,0 +1,51 @@
|
||||
--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 (1) {
|
||||
["parameter"]=>
|
||||
array(1) {
|
||||
["$class"]=>
|
||||
string(10) "<required>"
|
||||
}
|
||||
}
|
||||
[1]=>
|
||||
object(Autoloader)#%d (1) {
|
||||
["dir":"Autoloader":private]=>
|
||||
string(2) "d1"
|
||||
}
|
||||
[2]=>
|
||||
object(Autoloader)#%d (1) {
|
||||
["dir":"Autoloader":private]=>
|
||||
string(2) "d2"
|
||||
}
|
||||
}
|
||||
===DONE===
|
47
ext/spl/tests/spl_autoload_014.phpt
Normal file
47
ext/spl/tests/spl_autoload_014.phpt
Normal file
@ -0,0 +1,47 @@
|
||||
--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===
|
@ -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===
|
Loading…
Reference in New Issue
Block a user