From: Dmitry Stogov Date: Fri, 15 Feb 2008 07:44:46 +0000 (+0000) Subject: MFH: Fixed bug #43128 (Very long class name causes segfault) X-Git-Tag: php-5.2.6RC1~66 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f29c6b45a8ea3198245c03eaab174780c56b5332;p=php MFH: Fixed bug #43128 (Very long class name causes segfault) --- diff --git a/NEWS b/NEWS index edda002cd0..d774ef30ba 100644 --- 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 index 0000000000..4ee676a0a4 --- /dev/null +++ b/Zend/tests/bug43128.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #43128 Very long class name causes segfault +--FILE-- +$a(); // Fatal error + +if ($a instanceof $a); // Segmentation fault +new $a; // Segmentation fault +echo "ok\n"; +--EXPECT-- +ok diff --git a/Zend/zend.h b/Zend/zend.h index 6cc106403a..eb2bdb591f 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -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 diff --git a/Zend/zend_API.c b/Zend/zend_API.c index a2abd01759..43c75b3564 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -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**)®_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) { diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 5fbbd549cf..df7f22a844 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -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); } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index bcee0d8f91..e8832af142 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 9c816adf27..7e5074f752 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -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; } diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index e19657872d..f10a800b72 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -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; }