]> granicus.if.org Git - php/commitdiff
Fixed bug #40091 (spl_autoload_register with 2 instances of the same class).
authorIlia Alshanetsky <iliaa@php.net>
Wed, 10 Jan 2007 18:14:37 +0000 (18:14 +0000)
committerIlia Alshanetsky <iliaa@php.net>
Wed, 10 Jan 2007 18:14:37 +0000 (18:14 +0000)
NEWS
ext/spl/php_spl.c
ext/spl/tests/bug40091.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 529d3e4de0f35ad9957129a0a6662c952394d12c..fcf04118c6709efcdeebf49eb6a4d4ae39d5a464 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,8 @@ PHP                                                                        NEWS
 - Added CURLOPT_TCP_NODELAY constant to Curl extension. (Sara)
 - Improved proc_open(). Now on Windows it can run external commands not through
   CMD.EXE. (Dmitry)
+- Fixed bug #40091 (spl_autoload_register with 2 instances of the same
+  class). (Ilia)
 - Fixed bug #40083 (milter SAPI functions always return false/null). (Tony)
 - Fixed bug #40079 (php_get_current_user() not thread safe). (Ilia, wharmby
   at uk dot ibm dot com)
index b8e1cfbe199a87f9145d49306e27c6cd1a6f6ebc..98afefa9f89604c79b76288aa23fc0644f239ccb 100755 (executable)
@@ -444,10 +444,19 @@ PHP_FUNCTION(spl_autoload_register)
                        }
                }
        
-               lc_name = do_alloca(func_name_len + 1);
+               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 (SPL_G(autoload_functions) && zend_hash_exists(SPL_G(autoload_functions), (char*)lc_name, func_name_len+1)) {
+                       goto skip;                      
+               }
+
                if (obj_ptr && !(alfi.func_ptr->common.fn_flags & ZEND_ACC_STATIC)) {
+                       /* add object id to the hash to ensure uniqueness, for more reference look at bug #40091 */
+                       memcpy(lc_name + func_name_len, obj_ptr, sizeof(long));
+                       func_name_len += sizeof(long);
+                       lc_name[func_name_len] = '\0';
                        alfi.obj = *obj_ptr;
                        alfi.obj->refcount++;
                } else {
@@ -471,8 +480,8 @@ PHP_FUNCTION(spl_autoload_register)
                }
 
                zend_hash_add(SPL_G(autoload_functions), lc_name, func_name_len+1, &alfi.func_ptr, sizeof(autoload_func_info), NULL);
-
-               free_alloca(lc_name);
+skip:
+               efree(lc_name);
        }
 
        if (SPL_G(autoload_functions)) {
@@ -492,12 +501,13 @@ PHP_FUNCTION(spl_autoload_unregister)
        zval *zcallable;
        int success = FAILURE;
        zend_function *spl_func_ptr;
+       zval **obj_ptr;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zcallable) == FAILURE) {
                return;
        }
 
-       if (!zend_is_callable_ex(zcallable, IS_CALLABLE_CHECK_SYNTAX_ONLY, &func_name, &func_name_len, NULL, NULL, NULL TSRMLS_CC)) {
+       if (!zend_is_callable_ex(zcallable, IS_CALLABLE_CHECK_SYNTAX_ONLY, &func_name, &func_name_len, NULL, NULL, &obj_ptr TSRMLS_CC)) {
                if (func_name) {
                        efree(func_name);
                }
@@ -517,6 +527,13 @@ PHP_FUNCTION(spl_autoload_unregister)
                } else {
                        /* remove specific */
                        success = zend_hash_del(SPL_G(autoload_functions), func_name, func_name_len+1);
+                       if (success != SUCCESS && obj_ptr) {
+                               func_name = erealloc(func_name, func_name_len + 1 + sizeof(long));
+                               memcpy(func_name + func_name_len, obj_ptr, sizeof(long));
+                               func_name_len += sizeof(long);
+                               func_name[func_name_len] = '\0';
+                               success = zend_hash_del(SPL_G(autoload_functions), func_name, func_name_len+1);
+                       }
                }
        } else if (func_name_len == sizeof("spl_autoload")-1 && !strcmp(func_name, "spl_autoload")) {
                /* register single spl_autoload() */
diff --git a/ext/spl/tests/bug40091.phpt b/ext/spl/tests/bug40091.phpt
new file mode 100644 (file)
index 0000000..7d6210b
--- /dev/null
@@ -0,0 +1,39 @@
+--TEST--
+Bug #40091 (issue with spl_autoload_register() and 2 instances of the same class)
+--SKIPIF--
+<?php if (!extension_loaded("spl")) print "skip"; ?>
+--FILE--
+<?php
+class MyAutoloader {
+       function __construct($directory_to_use) {}
+       function autoload($class_name) {
+               // code to autoload based on directory
+       }
+}
+
+$autloader1 = new MyAutoloader('dir1');
+spl_autoload_register(array($autloader1, 'autoload'));
+
+$autloader2 = new MyAutoloader('dir2');
+spl_autoload_register(array($autloader2, 'autoload'));
+
+print_r(spl_autoload_functions());
+?>
+===DONE===
+--EXPECT--
+Array
+(
+    [0] => Array
+        (
+            [0] => MyAutoloader
+            [1] => autoload
+        )
+
+    [1] => Array
+        (
+            [0] => MyAutoloader
+            [1] => autoload
+        )
+
+)
+===DONE===