Browse Source

Fixed bug #43128 (Very long class name causes segfault)

experimental/phar_tar
Dmitry Stogov 19 years ago
parent
commit
47dc82ecb9
  1. 12
      TSRM/tsrm_config_common.h
  2. 5
      TSRM/tsrm_virtual_cwd.c
  3. 17
      Zend/tests/bug43128.phpt
  4. 14
      Zend/zend.h
  5. 17
      Zend/zend_API.c
  6. 1
      Zend/zend_compile.h
  7. 7
      Zend/zend_execute.c
  8. 5
      Zend/zend_strtod.c
  9. 9
      Zend/zend_vm_execute.h
  10. 9
      Zend/zend_vm_execute.skl
  11. 5
      ext/interbase/ibase_query.c
  12. 14
      ext/reflection/php_reflection.c
  13. 10
      main/main.c

12
TSRM/tsrm_config_common.h

@ -52,9 +52,17 @@ char *alloca ();
#endif #endif
#if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2)) #if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2))
# define tsrm_do_alloca(p) alloca(p)
# define tsrm_free_alloca(p)
# define TSRM_ALLOCA_MAX_SIZE 4096
# define TSRM_ALLOCA_FLAG(name) \
int name;
# define tsrm_do_alloca_ex(size, limit, use_heap) \
((use_heap = ((size) > (limit))) ? malloc(size) : alloca(size))
# define tsrm_do_alloca(size, use_heap) \
tsrm_do_alloca_ex(size, TSRM_ALLOCA_MAX_SIZE, use_heap)
# define tsrm_free_alloca(p, use_heap) \
do { if (use_heap) free(p); } while (0)
#else #else
# define TSRM_ALLOCA_FLAG(name)
# define tsrm_do_alloca(p) malloc(p) # define tsrm_do_alloca(p) malloc(p)
# define tsrm_free_alloca(p) free(p) # define tsrm_free_alloca(p) free(p)
#endif #endif

5
TSRM/tsrm_virtual_cwd.c

@ -777,6 +777,7 @@ CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path
int length = strlen(path); int length = strlen(path);
char *temp; char *temp;
int retval; int retval;
TSRM_ALLOCA_FLAG(use_heap)
if (length == 0) { if (length == 0) {
return 1; /* Can't cd to empty string */ return 1; /* Can't cd to empty string */
@ -793,14 +794,14 @@ CWD_API int virtual_chdir_file(const char *path, int (*p_chdir)(const char *path
if (length == COPY_WHEN_ABSOLUTE(path) && IS_ABSOLUTE_PATH(path, length+1)) { /* Also use trailing slash if this is absolute */ if (length == COPY_WHEN_ABSOLUTE(path) && IS_ABSOLUTE_PATH(path, length+1)) { /* Also use trailing slash if this is absolute */
length++; length++;
} }
temp = (char *) tsrm_do_alloca(length+1);
temp = (char *) tsrm_do_alloca(length+1, use_heap);
memcpy(temp, path, length); memcpy(temp, path, length);
temp[length] = 0; temp[length] = 0;
#if VIRTUAL_CWD_DEBUG #if VIRTUAL_CWD_DEBUG
fprintf (stderr, "Changing directory to %s\n", temp); fprintf (stderr, "Changing directory to %s\n", temp);
#endif #endif
retval = p_chdir(temp TSRMLS_CC); retval = p_chdir(temp TSRMLS_CC);
tsrm_free_alloca(temp);
tsrm_free_alloca(temp, use_heap);
return retval; return retval;
} }
/* }}} */ /* }}} */

17
Zend/tests/bug43128.phpt

@ -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

14
Zend/zend.h

@ -178,11 +178,19 @@ char *alloca ();
#endif #endif
#if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2)) && !(defined(ZTS) && defined(ZEND_WIN32)) && !(defined(ZTS) && defined(NETWARE)) && !(defined(ZTS) && defined(HPUX)) && !defined(DARWIN) #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 #else
# define ALLOCA_FLAG(name)
# define do_alloca(p) emalloc(p) # define do_alloca(p) emalloc(p)
# define free_alloca(p) efree(p)
# define free_alloca(p) efree(p)
#endif #endif
#if ZEND_DEBUG #if ZEND_DEBUG

17
Zend/zend_API.c

@ -2195,11 +2195,10 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
} }
} }
fname_len = strlen(ptr->fname); 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_ascii_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) { if (zend_ascii_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)&reg_function) == FAILURE) {
unload=1; unload=1;
free_alloca(lowercase_name);
efree(lowercase_name);
break; break;
} }
if (scope) { if (scope) {
@ -2245,7 +2244,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio
} }
ptr++; ptr++;
count++; count++;
free_alloca(lowercase_name);
efree(lowercase_name);
} }
if (unload) { /* before unloading, display all remaining bad function in the module */ if (unload) { /* before unloading, display all remaining bad function in the module */
if (scope) { if (scope) {
@ -3270,11 +3269,12 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, char *name, int name
if (UG(unicode)) { if (UG(unicode)) {
zstr uname; zstr uname;
int ret; int ret;
ALLOCA_FLAG(use_heap)
uname.u = do_alloca(UBYTES(name_length+1));
uname.u = do_alloca(UBYTES(name_length+1), use_heap);
u_charsToUChars(name, uname.u, name_length+1); u_charsToUChars(name, uname.u, name_length+1);
ret = zend_u_declare_property_ex(ce, IS_UNICODE, uname, name_length, property, access_type, doc_comment, doc_comment_len TSRMLS_CC); ret = zend_u_declare_property_ex(ce, IS_UNICODE, uname, name_length, property, access_type, doc_comment, doc_comment_len TSRMLS_CC);
free_alloca(uname.u);
free_alloca(uname.u, use_heap);
return ret; return ret;
} else { } else {
return zend_u_declare_property_ex(ce, IS_STRING, ZSTR(name), name_length, property, access_type, doc_comment, doc_comment_len TSRMLS_CC); return zend_u_declare_property_ex(ce, IS_STRING, ZSTR(name), name_length, property, access_type, doc_comment, doc_comment_len TSRMLS_CC);
@ -3293,11 +3293,12 @@ ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_le
if (UG(unicode)) { if (UG(unicode)) {
zstr uname; zstr uname;
int ret; int ret;
ALLOCA_FLAG(use_heap)
uname.u = do_alloca(UBYTES(name_length+1));
uname.u = do_alloca(UBYTES(name_length+1), use_heap);
u_charsToUChars(name, uname.u, name_length+1); u_charsToUChars(name, uname.u, name_length+1);
ret = zend_u_declare_property_ex(ce, IS_UNICODE, uname, name_length, property, access_type, NULL_ZSTR, 0 TSRMLS_CC); ret = zend_u_declare_property_ex(ce, IS_UNICODE, uname, name_length, property, access_type, NULL_ZSTR, 0 TSRMLS_CC);
free_alloca(uname.u);
free_alloca(uname.u, use_heap);
return ret; return ret;
} else { } else {
return zend_u_declare_property_ex(ce, IS_STRING, ZSTR(name), name_length, property, access_type, NULL_ZSTR, 0 TSRMLS_CC); return zend_u_declare_property_ex(ce, IS_STRING, ZSTR(name), name_length, property, access_type, NULL_ZSTR, 0 TSRMLS_CC);

1
Zend/zend_compile.h

@ -304,6 +304,7 @@ struct _zend_execute_data {
union _temp_variable *Ts; union _temp_variable *Ts;
zval ***CVs; zval ***CVs;
zend_bool original_in_execution; zend_bool original_in_execution;
ALLOCA_FLAG(use_heap)
HashTable *symbol_table; HashTable *symbol_table;
struct _zend_execute_data *prev_execute_data; struct _zend_execute_data *prev_execute_data;
zval *old_error_reporting; zval *old_error_reporting;

7
Zend/zend_execute.c

@ -1447,12 +1447,7 @@ ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_v
} }
#define ZEND_VM_EXIT_FROM_EXECUTE_LOOP() \ #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(in_execution) = EX(original_in_execution); \
EG(current_execute_data) = EX(prev_execute_data); \ EG(current_execute_data) = EX(prev_execute_data); \
EG(opline_ptr) = NULL; EG(opline_ptr) = NULL;

5
Zend/zend_strtod.c

@ -2603,6 +2603,7 @@ ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr) /* {{{ */
const UChar *u = nptr, *nstart; const UChar *u = nptr, *nstart;
UChar c = *u; UChar c = *u;
int any = 0; int any = 0;
ALLOCA_FLAG(use_heap)
while (u_isspace(c)) { while (u_isspace(c)) {
c = *++u; c = *++u;
@ -2653,7 +2654,7 @@ ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr) /* {{{ */
if (length < sizeof(buf)) { if (length < sizeof(buf)) {
numbuf = buf; numbuf = buf;
} else { } else {
numbuf = (char *) do_alloca(length + 1);
numbuf = (char *) do_alloca(length + 1, use_heap);
} }
bufpos = numbuf; bufpos = numbuf;
@ -2666,7 +2667,7 @@ ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr) /* {{{ */
value = zend_strtod(numbuf, NULL); value = zend_strtod(numbuf, NULL);
if (numbuf != buf) { if (numbuf != buf) {
free_alloca(numbuf);
free_alloca(numbuf, use_heap);
} }
if (endptr != NULL) { if (endptr != NULL) {

9
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(called_scope) = NULL;
EX(object) = NULL; EX(object) = NULL;
EX(old_error_reporting) = 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 { } 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); memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var);
EX(op_array) = op_array; EX(op_array) = op_array;
EX(original_in_execution) = EG(in_execution); EX(original_in_execution) = EG(in_execution);

9
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(called_scope) = NULL;
EX(object) = NULL; EX(object) = NULL;
EX(old_error_reporting) = 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 { } 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); memset(EX(CVs), 0, sizeof(zval**) * op_array->last_var);
EX(op_array) = op_array; EX(op_array) = op_array;
EX(original_in_execution) = EG(in_execution); EX(original_in_execution) = EG(in_execution);

5
ext/interbase/ibase_query.c

@ -1836,6 +1836,7 @@ PHP_FUNCTION(ibase_execute)
zval *query, ***args = NULL; zval *query, ***args = NULL;
ibase_query *ib_query; ibase_query *ib_query;
ibase_result *result = NULL; ibase_result *result = NULL;
ALLOCA_FLAG(use_heap)
RESET_ERRMSG; RESET_ERRMSG;
@ -1859,7 +1860,7 @@ PHP_FUNCTION(ibase_execute)
} }
} else if (bind_n > 0) { /* have variables to bind */ } else if (bind_n > 0) { /* have variables to bind */
args = (zval ***) do_alloca(ZEND_NUM_ARGS() * sizeof(zval **));
args = (zval ***) do_alloca(ZEND_NUM_ARGS() * sizeof(zval **), use_heap);
if (FAILURE == zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args)) { if (FAILURE == zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args)) {
break; break;
@ -1900,7 +1901,7 @@ PHP_FUNCTION(ibase_execute)
} while (0); } while (0);
if (args) { if (args) {
free_alloca(args);
free_alloca(args, use_heap);
} }
} }
/* }}} */ /* }}} */

14
ext/reflection/php_reflection.c

@ -1065,14 +1065,15 @@ static void reflection_extension_factory(zval *object, const char *name_str TSRM
int name_len = strlen(name_str); int name_len = strlen(name_str);
char *lcname; char *lcname;
struct _zend_module_entry *module; struct _zend_module_entry *module;
ALLOCA_FLAG(use_heap)
lcname = do_alloca(name_len + 1);
lcname = do_alloca(name_len + 1, use_heap);
zend_str_tolower_copy(lcname, name_str, name_len); zend_str_tolower_copy(lcname, name_str, name_len);
if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) { if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) {
free_alloca(lcname);
free_alloca(lcname, use_heap);
return; return;
} }
free_alloca(lcname);
free_alloca(lcname, use_heap);
reflection_instantiate(reflection_extension_ptr, object TSRMLS_CC); reflection_instantiate(reflection_extension_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC); intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
@ -4240,6 +4241,7 @@ ZEND_METHOD(reflection_extension, __construct)
zend_module_entry *module; zend_module_entry *module;
char *name_str; char *name_str;
int name_len; int name_len;
ALLOCA_FLAG(use_heap)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) { if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
return; return;
@ -4250,15 +4252,15 @@ ZEND_METHOD(reflection_extension, __construct)
if (intern == NULL) { if (intern == NULL) {
return; return;
} }
lcname = do_alloca(name_len + 1);
lcname = do_alloca(name_len + 1, use_heap);
zend_str_tolower_copy(lcname, name_str, name_len); zend_str_tolower_copy(lcname, name_str, name_len);
if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) { if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) {
free_alloca(lcname);
free_alloca(lcname, use_heap);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Extension %s does not exist", name_str); "Extension %s does not exist", name_str);
return; return;
} }
free_alloca(lcname);
free_alloca(lcname, use_heap);
MAKE_STD_ZVAL(name); MAKE_STD_ZVAL(name);
ZVAL_ASCII_STRING(name, module->name, 1); ZVAL_ASCII_STRING(name, module->name, 1);
zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL); zend_ascii_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);

10
main/main.c

@ -2090,6 +2090,7 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC)
int old_cwd_fd = -1; int old_cwd_fd = -1;
#else #else
char *old_cwd; char *old_cwd;
ALLOCA_FLAG(use_heap)
#endif #endif
int retval = 0; int retval = 0;
@ -2100,7 +2101,7 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC)
} }
#ifndef HAVE_BROKEN_GETCWD #ifndef HAVE_BROKEN_GETCWD
# define OLD_CWD_SIZE 4096 # define OLD_CWD_SIZE 4096
old_cwd = do_alloca(OLD_CWD_SIZE);
old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
old_cwd[0] = '\0'; old_cwd[0] = '\0';
#endif #endif
@ -2177,7 +2178,7 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC)
if (old_cwd[0] != '\0') { if (old_cwd[0] != '\0') {
VCWD_CHDIR(old_cwd); VCWD_CHDIR(old_cwd);
} }
free_alloca(old_cwd);
free_alloca(old_cwd, use_heap);
#endif #endif
return retval; return retval;
} }
@ -2188,10 +2189,11 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC)
PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval **ret TSRMLS_DC) PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval **ret TSRMLS_DC)
{ {
char *old_cwd; char *old_cwd;
ALLOCA_FLAG(use_heap)
EG(exit_status) = 0; EG(exit_status) = 0;
#define OLD_CWD_SIZE 4096 #define OLD_CWD_SIZE 4096
old_cwd = do_alloca(OLD_CWD_SIZE);
old_cwd = do_alloca(OLD_CWD_SIZE, use_heap);
old_cwd[0] = '\0'; old_cwd[0] = '\0';
zend_try { zend_try {
@ -2212,7 +2214,7 @@ PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval **ret
VCWD_CHDIR(old_cwd); VCWD_CHDIR(old_cwd);
} }
free_alloca(old_cwd);
free_alloca(old_cwd, use_heap);
return EG(exit_status); return EG(exit_status);
} }
/* }}} */ /* }}} */

Loading…
Cancel
Save