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

Reply via email to