diff options
| author | Dmitry Stogov <dmitry@php.net> | 2007-11-22 13:27:13 +0000 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@php.net> | 2007-11-22 13:27:13 +0000 |
| commit | 648fbe9d5838073154f3737829d5298502184343 (patch) | |
| tree | bd21fcbb0af89d62032a842dc4e6f29518fa3cdf /Zend | |
| parent | 1836daf7f9f3ab088a65fd8c0b8c9421d6550be5 (diff) | |
| download | php-git-648fbe9d5838073154f3737829d5298502184343.tar.gz | |
Fixed bug #43128 (Very long class name causes segfault)
Diffstat (limited to 'Zend')
| -rwxr-xr-x | Zend/tests/bug43128.phpt | 15 | ||||
| -rw-r--r-- | Zend/zend.h | 12 | ||||
| -rw-r--r-- | Zend/zend_API.c | 7 | ||||
| -rw-r--r-- | Zend/zend_builtin_functions.c | 14 | ||||
| -rw-r--r-- | Zend/zend_compile.c | 5 | ||||
| -rw-r--r-- | Zend/zend_compile.h | 1 | ||||
| -rw-r--r-- | Zend/zend_execute.c | 7 | ||||
| -rw-r--r-- | Zend/zend_execute_API.c | 17 | ||||
| -rw-r--r-- | Zend/zend_object_handlers.c | 7 | ||||
| -rw-r--r-- | Zend/zend_vm_execute.h | 9 | ||||
| -rw-r--r-- | Zend/zend_vm_execute.skl | 9 |
11 files changed, 64 insertions, 39 deletions
diff --git a/Zend/tests/bug43128.phpt b/Zend/tests/bug43128.phpt new file mode 100755 index 0000000000..e5969c3b62 --- /dev/null +++ b/Zend/tests/bug43128.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #43128 Very long class name causes segfault +--FILE-- +<?php + +$a = str_repeat("a", 10 * 1024 * 1024); + +# call_user_func($a); // Warning +# $a->$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 75201c1190..211733aa8e 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -177,9 +177,17 @@ char *alloca (); #endif #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_ex(size, limit, use_heap) \ + ((use_heap = (UNEXPECTED((size) > (limit)))) ? emalloc(size) : alloca(size)) +# define do_alloca(size, use_heap) \ + do_alloca_ex(size, ZEND_ALLOCA_MAX_SIZE, use_heap) +# define free_alloca(p, use_heap) \ + do { if (UNEXPECTED(use_heap)) efree(p); } while (0) #else +# define ALLOCA_FLAG(name) # define do_alloca(p) emalloc(p) # define free_alloca(p) efree(p) #endif diff --git a/Zend/zend_API.c b/Zend/zend_API.c index fbf73e8e76..056b3b6879 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1863,11 +1863,10 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio } } 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) { @@ -1909,7 +1908,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio } 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 27559f59f4..f7f08e91d8 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1034,19 +1034,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(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(lc_name, use_heap); RETURN_BOOL(found == SUCCESS && !((*ce)->ce_flags & ZEND_ACC_INTERFACE)); } @@ -1065,19 +1066,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(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(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 5da1f78862..bdb51ef121 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1088,6 +1088,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) { @@ -1148,7 +1149,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(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 */ @@ -1184,7 +1185,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(short_class_name, use_heap); } efree(lcname); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 9056c1bb1d..a2a8dcd053 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -299,6 +299,7 @@ struct _zend_execute_data { union _temp_variable *Ts; zval ***CVs; zend_bool original_in_execution; + ALLOCA_FLAG(use_heap) HashTable *symbol_table; struct _zend_execute_data *prev_execute_data; zval *old_error_reporting; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 797fbe8446..508cc974c5 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1427,12 +1427,7 @@ ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_v } #define ZEND_VM_EXIT_FROM_EXECUTE_LOOP() \ - free_alloca(EX(CVs)); \ - if (EX(op_array)->T < TEMP_VAR_STACK_LIMIT) { \ - free_alloca(EX(Ts)); \ - } else { \ - efree(EX(Ts)); \ - } \ + free_alloca(EX(CVs), EX(use_heap)); \ EG(in_execution) = EX(original_in_execution); \ EG(current_execute_data) = EX(prev_execute_data); \ EG(opline_ptr) = NULL; diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index fdff4d9acc..ff76d3aa4f 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1082,15 +1082,16 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut char *lc_name; char *lc_free; 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_free = lc_name = do_alloca(name_length + 1); + lc_free = lc_name = do_alloca(name_length + 1, use_heap); zend_str_tolower_copy(lc_name, name, name_length); if (lc_name[0] == ':' && lc_name[1] == ':') { @@ -1099,7 +1100,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut } if (zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce) == SUCCESS) { - free_alloca(lc_free); + free_alloca(lc_free, use_heap); return SUCCESS; } @@ -1107,7 +1108,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut * (doesn't impact fuctionality of __autoload() */ if (!use_autoload || zend_is_compiling(TSRMLS_C)) { - free_alloca(lc_free); + free_alloca(lc_free, use_heap); return FAILURE; } @@ -1117,7 +1118,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut } if (zend_hash_add(EG(in_autoload), lc_name, name_length + 1, (void**)&dummy, sizeof(char), NULL) == FAILURE) { - free_alloca(lc_free); + free_alloca(lc_free, use_heap); return FAILURE; } @@ -1155,12 +1156,12 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut if (retval == FAILURE) { EG(exception) = exception; - free_alloca(lc_free); + free_alloca(lc_free, use_heap); return FAILURE; } if (EG(exception) && exception) { - free_alloca(lc_free); + free_alloca(lc_free, 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; } @@ -1172,7 +1173,7 @@ ZEND_API int zend_lookup_class_ex(const char *name, int name_length, int use_aut } retval = zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce); - free_alloca(lc_free); + free_alloca(lc_free, use_heap); return retval; } /* }}} */ diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 017f3df635..56ff4ab1b2 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -776,14 +776,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(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(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; @@ -838,7 +839,7 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method } } - free_alloca(lc_method_name); + free_alloca(lc_method_name, use_heap); return fbc; } /* }}} */ diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 098aaa6f35..e6c7fb1d1f 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -45,12 +45,13 @@ ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) EX(called_scope) = NULL; EX(object) = NULL; EX(old_error_reporting) = NULL; - if (op_array->T < TEMP_VAR_STACK_LIMIT) { - EX(Ts) = (temp_variable *) do_alloca(sizeof(temp_variable) * op_array->T); + if (EXPECTED(op_array->T < TEMP_VAR_STACK_LIMIT && op_array->last_var < TEMP_VAR_STACK_LIMIT)) { + EX(CVs) = (zval***)do_alloca(sizeof(zval**) * op_array->last_var + sizeof(temp_variable) * op_array->T, EX(use_heap)); } else { - EX(Ts) = (temp_variable *) safe_emalloc(sizeof(temp_variable), op_array->T, 0); + EX(use_heap) = 1; + EX(CVs) = (zval***)safe_emalloc(sizeof(temp_variable), op_array->T, sizeof(zval**) * op_array->last_var); } - EX(CVs) = (zval***)do_alloca(sizeof(zval**) * op_array->last_var); + EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var); memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); EX(op_array) = op_array; EX(original_in_execution) = EG(in_execution); diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 1f6116b08a..95d13606e4 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -16,12 +16,13 @@ ZEND_API void {%EXECUTOR_NAME%}(zend_op_array *op_array TSRMLS_DC) EX(called_scope) = NULL; EX(object) = NULL; EX(old_error_reporting) = NULL; - if (op_array->T < TEMP_VAR_STACK_LIMIT) { - EX(Ts) = (temp_variable *) do_alloca(sizeof(temp_variable) * op_array->T); + if (EXPECTED(op_array->T < TEMP_VAR_STACK_LIMIT && op_array->last_var < TEMP_VAR_STACK_LIMIT)) { + EX(CVs) = (zval***)do_alloca(sizeof(zval**) * op_array->last_var + sizeof(temp_variable) * op_array->T, EX(use_heap)); } else { - EX(Ts) = (temp_variable *) safe_emalloc(sizeof(temp_variable), op_array->T, 0); + EX(use_heap) = 1; + EX(CVs) = (zval***)safe_emalloc(sizeof(temp_variable), op_array->T, sizeof(zval**) * op_array->last_var); } - EX(CVs) = (zval***)do_alloca(sizeof(zval**) * op_array->last_var); + EX(Ts) = (temp_variable *)(EX(CVs) + op_array->last_var); memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var); EX(op_array) = op_array; EX(original_in_execution) = EG(in_execution); |
