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)
--- /dev/null
+--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
#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
}
}
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) {
}
ptr++;
count++;
- free_alloca(lowercase_name);
+ efree(lowercase_name);
}
if (unload) { /* before unloading, display all remaining bad function in the module */
if (scope) {
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));
}
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);
}
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) {
}
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 */
} 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);
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;
}
* (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;
}
}
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;
}
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;
}
}
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;
}
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;
}
}
- free_alloca(lc_method_name);
+ free_alloca_with_limit(lc_method_name, use_heap);
return fbc;
}