]> granicus.if.org Git - php/commitdiff
MFH: Fixed bug #43128 (Very long class name causes segfault)
authorDmitry Stogov <dmitry@php.net>
Fri, 15 Feb 2008 07:44:46 +0000 (07:44 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 15 Feb 2008 07:44:46 +0000 (07:44 +0000)
NEWS
Zend/tests/bug43128.phpt [new file with mode: 0755]
Zend/zend.h
Zend/zend_API.c
Zend/zend_builtin_functions.c
Zend/zend_compile.c
Zend/zend_execute_API.c
Zend/zend_object_handlers.c

diff --git a/NEWS b/NEWS
index edda002cd06d5e527e49da000ed7e4cb009a38c2..d774ef30ba88d5060b74627b3649364b214af240 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -95,6 +95,7 @@ PHP                                                                        NEWS
   truncation). (Ilia)
 - Fixed bug #43175 (__destruct() throwing an exception with __call() causes
   segfault). (Dmitry)
+- Fixed bug #43128 (Very long class name causes segfault). (Dmitry)
 - Fixed bug #43105 (PHP seems to fail to close open files). (Hannes)
 - Fixed bug #42978 (mismatch between number of bound params and values causes
   a crash in pdo_pgsql). (Ilia)
diff --git a/Zend/tests/bug43128.phpt b/Zend/tests/bug43128.phpt
new file mode 100755 (executable)
index 0000000..4ee676a
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #43128 Very long class name causes segfault 
+--FILE--
+<?php
+
+$a = str_repeat("a", 10 * 1024 * 1024);
+
+eval("class $a {}");
+
+# call_user_func($a); // Warning
+# $a->$a();           // Fatal error
+
+if ($a instanceof $a); // Segmentation fault
+new $a;                // Segmentation fault
+echo "ok\n";
+--EXPECT--
+ok
index 6cc106403a7c224de92dd8ad0d75b613109a6547..eb2bdb591fc8244092f206bc068da63a7526a4ec 100644 (file)
@@ -181,9 +181,21 @@ char *alloca ();
 #if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2)) && !(defined(ZTS) && defined(ZEND_WIN32)) && !(defined(ZTS) && defined(NETWARE)) && !(defined(ZTS) && defined(HPUX)) && !defined(DARWIN)
 # define do_alloca(p) alloca(p)
 # define free_alloca(p)
+# define ZEND_ALLOCA_MAX_SIZE (32 * 1024)
+# define ALLOCA_FLAG(name) \
+       zend_bool name;
+# define do_alloca_with_limit_ex(size, limit, use_heap) \
+       ((use_heap = ((size) > (limit))) ? emalloc(size) : alloca(size))
+# define do_alloca_with_limit(size, use_heap) \
+       do_alloca_with_limit_ex(size, ZEND_ALLOCA_MAX_SIZE, use_heap)
+# define free_alloca_with_limit(p, use_heap) \
+       do { if (use_heap) efree(p); } while (0)
 #else
 # define do_alloca(p)          emalloc(p)
 # define free_alloca(p)        efree(p)
+# define ALLOCA_FLAG(name)
+# define do_alloca_with_limit(p, use_heap)             emalloc(p)
+# define free_alloca_with_limit(p, use_heap)   efree(p)
 #endif
 
 #if ZEND_DEBUG
index a2abd0175929f06e70dd7720b1cd1990768c07fc..43c75b3564d05f8aca5150c48ee4aeabe14f9d9c 100644 (file)
@@ -1723,11 +1723,10 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
                        }
                }
                fname_len = strlen(ptr->fname);
-               lowercase_name = do_alloca(fname_len+1);
-               zend_str_tolower_copy(lowercase_name, ptr->fname, fname_len);
+               lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len);
                if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) {
                        unload=1;
-                       free_alloca(lowercase_name);
+                       efree(lowercase_name);
                        break;
                }
                if (scope) {
@@ -1767,7 +1766,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
                }
                ptr++;
                count++;
-               free_alloca(lowercase_name);
+               efree(lowercase_name);
        }
        if (unload) { /* before unloading, display all remaining bad function in the module */
                if (scope) {
index 5fbbd549cf9a72b1d0e6f1ca621b7470158f8ec2..df7f22a84433df95c21f4d061ceca5cdc043b593 100644 (file)
@@ -1013,19 +1013,20 @@ ZEND_FUNCTION(class_exists)
        char *class_name, *lc_name;
        zend_class_entry **ce;
        int class_name_len;
-       zend_bool autoload = 1;
        int found;
+       zend_bool autoload = 1;
+       ALLOCA_FLAG(use_heap)
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &class_name, &class_name_len, &autoload) == FAILURE) {
                return;
        }
 
        if (!autoload) {
-               lc_name = do_alloca(class_name_len + 1);
+               lc_name = do_alloca_with_limit(class_name_len + 1, use_heap);
                zend_str_tolower_copy(lc_name, class_name, class_name_len);
        
                found = zend_hash_find(EG(class_table), lc_name, class_name_len+1, (void **) &ce);
-               free_alloca(lc_name);
+               free_alloca_with_limit(lc_name, use_heap);
                RETURN_BOOL(found == SUCCESS && !((*ce)->ce_flags & ZEND_ACC_INTERFACE));
        }
 
@@ -1044,19 +1045,20 @@ ZEND_FUNCTION(interface_exists)
        char *iface_name, *lc_name;
        zend_class_entry **ce;
        int iface_name_len;
-       zend_bool autoload = 1;
        int found;
+       zend_bool autoload = 1;
+       ALLOCA_FLAG(use_heap)
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &iface_name, &iface_name_len, &autoload) == FAILURE) {
                return;
        }
 
        if (!autoload) {
-               lc_name = do_alloca(iface_name_len + 1);
+               lc_name = do_alloca_with_limit(iface_name_len + 1, use_heap);
                zend_str_tolower_copy(lc_name, iface_name, iface_name_len);
        
                found = zend_hash_find(EG(class_table), lc_name, iface_name_len+1, (void **) &ce);
-               free_alloca(lc_name);
+               free_alloca_with_limit(lc_name, use_heap);
                RETURN_BOOL(found == SUCCESS && (*ce)->ce_flags & ZEND_ACC_INTERFACE);
        }
 
index bcee0d8f9152f54ef0eeb7db6758a1622e4d0c71..e8832af142683053e02758fb98ee0c7cc7f08fd8 100644 (file)
@@ -1100,6 +1100,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
        zend_uint fn_flags;
        char *lcname;
        zend_bool orig_interactive;
+       ALLOCA_FLAG(use_heap)
 
        if (is_method) {
                if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
@@ -1160,7 +1161,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
                }
 
                if (!(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
-                       short_class_name = do_alloca(short_class_name_length + 1);
+                       short_class_name = do_alloca_with_limit(short_class_name_length + 1, use_heap);
                        zend_str_tolower_copy(short_class_name, CG(active_class_entry)->name, short_class_name_length);
                        /* Improve after RC: cache the lowercase class name */
 
@@ -1194,7 +1195,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
                        } else if (!(fn_flags & ZEND_ACC_STATIC)) {
                                CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
                        }
-                       free_alloca(short_class_name);
+                       free_alloca_with_limit(short_class_name, use_heap);
                }
 
                efree(lcname);
index 9c816adf27ce591eb5b259e7247ca93a5782ab06..7e5074f752a7652e7a5db6e05148f71c9abab7c6 100644 (file)
@@ -1034,19 +1034,20 @@ ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload,
        int retval;
        char *lc_name;
        zval *exception;
-       char dummy = 1;
        zend_fcall_info fcall_info;
        zend_fcall_info_cache fcall_cache;
+       char dummy = 1;
+       ALLOCA_FLAG(use_heap)
 
        if (name == NULL || !name_length) {
                return FAILURE;
        }
        
-       lc_name = do_alloca(name_length + 1);
+       lc_name = do_alloca_with_limit(name_length + 1, use_heap);
        zend_str_tolower_copy(lc_name, name, name_length);
 
        if (zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce) == SUCCESS) {
-               free_alloca(lc_name);
+               free_alloca_with_limit(lc_name, use_heap);
                return SUCCESS;
        }
 
@@ -1054,7 +1055,7 @@ ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload,
         * (doesn't impact fuctionality of __autoload()
        */
        if (!use_autoload || zend_is_compiling(TSRMLS_C)) {
-               free_alloca(lc_name);
+               free_alloca_with_limit(lc_name, use_heap);
                return FAILURE;
        }
 
@@ -1064,7 +1065,7 @@ ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload,
        }
        
        if (zend_hash_add(EG(in_autoload), lc_name, name_length+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
-               free_alloca(lc_name);
+               free_alloca_with_limit(lc_name, use_heap);
                return FAILURE;
        }
 
@@ -1102,12 +1103,12 @@ ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload,
 
        if (retval == FAILURE) {
                EG(exception) = exception;
-               free_alloca(lc_name);
+               free_alloca_with_limit(lc_name, use_heap);
                return FAILURE;
        }
 
        if (EG(exception) && exception) {
-               free_alloca(lc_name);
+               free_alloca_with_limit(lc_name, use_heap);
                zend_error(E_ERROR, "Function %s(%s) threw an exception of type '%s'", ZEND_AUTOLOAD_FUNC_NAME, name, Z_OBJCE_P(EG(exception))->name);
                return FAILURE;
        }
@@ -1119,7 +1120,7 @@ ZEND_API int zend_lookup_class_ex(char *name, int name_length, int use_autoload,
        }
 
        retval = zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce);
-       free_alloca(lc_name);
+       free_alloca_with_limit(lc_name, use_heap);
        return retval;
 }
 
index e19657872df2c7a05b5d638aa96f2bd24461b665..f10a800b7237f501aa4cd54c7ddb2a004122a1d3 100644 (file)
@@ -758,14 +758,15 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
        zend_function *fbc;
        char *lc_method_name;
        zval *object = *object_ptr;
+       ALLOCA_FLAG(use_heap)
        
-       lc_method_name = do_alloca(method_len+1);
+       lc_method_name = do_alloca_with_limit(method_len+1, use_heap);
        /* Create a zend_copy_str_tolower(dest, src, src_length); */
        zend_str_tolower_copy(lc_method_name, method_name, method_len);
                
        zobj = Z_OBJ_P(object);
        if (zend_hash_find(&zobj->ce->function_table, lc_method_name, method_len+1, (void **)&fbc) == FAILURE) {
-               free_alloca(lc_method_name);
+               free_alloca_with_limit(lc_method_name, use_heap);
                if (zobj->ce->__call) {
                        zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
                        call_user_call->type = ZEND_INTERNAL_FUNCTION;
@@ -820,7 +821,7 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
                }
        }
 
-       free_alloca(lc_method_name);
+       free_alloca_with_limit(lc_method_name, use_heap);
        return fbc;
 }