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
#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
# define TSRM_ALLOCA_FLAG(name)
# define tsrm_do_alloca(p) malloc(p)
# define tsrm_free_alloca(p) free(p)
#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);
char *temp;
int retval;
TSRM_ALLOCA_FLAG(use_heap)
if (length == 0) {
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 */
length++;
}
temp = (char *) tsrm_do_alloca(length+1);
temp = (char *) tsrm_do_alloca(length+1, use_heap);
memcpy(temp, path, length);
temp[length] = 0;
#if VIRTUAL_CWD_DEBUG
fprintf (stderr, "Changing directory to %s\n", temp);
#endif
retval = p_chdir(temp TSRMLS_CC);
tsrm_free_alloca(temp);
tsrm_free_alloca(temp, use_heap);
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
#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)
# define free_alloca(p) efree(p)
#endif
#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);
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) {
unload=1;
free_alloca(lowercase_name);
efree(lowercase_name);
break;
}
if (scope) {
@ -2245,7 +2244,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) {
@ -3270,11 +3269,12 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, char *name, int name
if (UG(unicode)) {
zstr uname;
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);
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;
} else {
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)) {
zstr uname;
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);
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;
} else {
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;
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;

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() \
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;

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

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(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);

5
ext/interbase/ibase_query.c

@ -1836,6 +1836,7 @@ PHP_FUNCTION(ibase_execute)
zval *query, ***args = NULL;
ibase_query *ib_query;
ibase_result *result = NULL;
ALLOCA_FLAG(use_heap)
RESET_ERRMSG;
@ -1859,7 +1860,7 @@ PHP_FUNCTION(ibase_execute)
}
} 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)) {
break;
@ -1900,7 +1901,7 @@ PHP_FUNCTION(ibase_execute)
} while (0);
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);
char *lcname;
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);
if (zend_hash_find(&module_registry, lcname, name_len + 1, (void **)&module) == FAILURE) {
free_alloca(lcname);
free_alloca(lcname, use_heap);
return;
}
free_alloca(lcname);
free_alloca(lcname, use_heap);
reflection_instantiate(reflection_extension_ptr, 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;
char *name_str;
int name_len;
ALLOCA_FLAG(use_heap)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
return;
@ -4250,15 +4252,15 @@ ZEND_METHOD(reflection_extension, __construct)
if (intern == NULL) {
return;
}
lcname = do_alloca(name_len + 1);
lcname = do_alloca(name_len + 1, use_heap);
zend_str_tolower_copy(lcname, name_str, name_len);
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,
"Extension %s does not exist", name_str);
return;
}
free_alloca(lcname);
free_alloca(lcname, use_heap);
MAKE_STD_ZVAL(name);
ZVAL_ASCII_STRING(name, module->name, 1);
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;
#else
char *old_cwd;
ALLOCA_FLAG(use_heap)
#endif
int retval = 0;
@ -2100,7 +2101,7 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC)
}
#ifndef HAVE_BROKEN_GETCWD
# 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';
#endif
@ -2177,7 +2178,7 @@ PHPAPI int php_execute_script(zend_file_handle *primary_file TSRMLS_DC)
if (old_cwd[0] != '\0') {
VCWD_CHDIR(old_cwd);
}
free_alloca(old_cwd);
free_alloca(old_cwd, use_heap);
#endif
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)
{
char *old_cwd;
ALLOCA_FLAG(use_heap)
EG(exit_status) = 0;
#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';
zend_try {
@ -2212,7 +2214,7 @@ PHPAPI int php_execute_simple_script(zend_file_handle *primary_file, zval **ret
VCWD_CHDIR(old_cwd);
}
free_alloca(old_cwd);
free_alloca(old_cwd, use_heap);
return EG(exit_status);
}
/* }}} */

Loading…
Cancel
Save