diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | Zend/Makefile.am | 2 | ||||
-rw-r--r-- | Zend/Zend.dsp | 8 | ||||
-rw-r--r-- | Zend/ZendTS.dsp | 8 | ||||
-rw-r--r-- | Zend/zend.c | 3 | ||||
-rw-r--r-- | Zend/zend.h | 5 | ||||
-rw-r--r-- | Zend/zend_API.c | 34 | ||||
-rw-r--r-- | Zend/zend_builtin_functions.c | 2 | ||||
-rw-r--r-- | Zend/zend_compile.c | 65 | ||||
-rw-r--r-- | Zend/zend_compile.h | 2 | ||||
-rw-r--r-- | Zend/zend_constants.c | 12 | ||||
-rw-r--r-- | Zend/zend_execute.c | 20 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 6 | ||||
-rw-r--r-- | Zend/zend_globals.h | 12 | ||||
-rw-r--r-- | Zend/zend_hash.c | 71 | ||||
-rw-r--r-- | Zend/zend_hash.h | 2 | ||||
-rw-r--r-- | Zend/zend_language_scanner.l | 8 | ||||
-rw-r--r-- | Zend/zend_opcode.c | 6 | ||||
-rw-r--r-- | Zend/zend_operators.c | 72 | ||||
-rw-r--r-- | Zend/zend_string.c | 229 | ||||
-rw-r--r-- | Zend/zend_string.h | 67 | ||||
-rw-r--r-- | Zend/zend_variables.c | 6 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 22 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 274 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | ext/filter/sanitizing_filters.c | 12 | ||||
-rw-r--r-- | ext/phar/phar.c | 44 | ||||
-rw-r--r-- | ext/standard/array.c | 16 | ||||
-rw-r--r-- | ext/standard/string.c | 16 | ||||
-rw-r--r-- | win32/build/config.w32 | 2 |
30 files changed, 838 insertions, 192 deletions
@@ -4,6 +4,8 @@ - Upgraded bundled sqlite to version 3.6.23.1. (Ilia) - Upgraded bundled PCRE to version 8.02. (Ilia) +- Added concept of interned strings. All strings constants known at compile + time are allocated in a single copy and never changed. (Dmitry) - Added an optimization which saves memory and emalloc/efree calls for empty HashTables (Stas, Dmitry) - Added Tokyo Cabinet abstract DB support to ext/dba. (Michael Maclean) diff --git a/Zend/Makefile.am b/Zend/Makefile.am index 219d2d3fc9..04b51081bf 100644 --- a/Zend/Makefile.am +++ b/Zend/Makefile.am @@ -17,7 +17,7 @@ libZend_la_SOURCES=\ zend_objects_API.c zend_ts_hash.c zend_stream.c \ zend_default_classes.c \ zend_iterators.c zend_interfaces.c zend_exceptions.c \ - zend_strtod.c zend_closures.c zend_float.c + zend_strtod.c zend_closures.c zend_float.c zend_string.c libZend_la_LDFLAGS = libZend_la_LIBADD = @ZEND_EXTRA_LIBS@ diff --git a/Zend/Zend.dsp b/Zend/Zend.dsp index 0a7ed77534..2a05c131e4 100644 --- a/Zend/Zend.dsp +++ b/Zend/Zend.dsp @@ -243,6 +243,10 @@ SOURCE=.\zend_stream.c # End Source File
# Begin Source File
+SOURCE=.\zend_string.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.c
# End Source File
# Begin Source File
@@ -411,6 +415,10 @@ SOURCE=.\zend_stream.h # End Source File
# Begin Source File
+SOURCE=.\zend_string.h
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.h
# End Source File
# Begin Source File
diff --git a/Zend/ZendTS.dsp b/Zend/ZendTS.dsp index 2295b89ebb..c08cc77faa 100644 --- a/Zend/ZendTS.dsp +++ b/Zend/ZendTS.dsp @@ -273,6 +273,10 @@ SOURCE=.\zend_stream.c # End Source File
# Begin Source File
+SOURCE=.\zend_string.c
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.c
# End Source File
# Begin Source File
@@ -445,6 +449,10 @@ SOURCE=.\zend_stream.h # End Source File
# Begin Source File
+SOURCE=.\zend_string.h
+# End Source File
+# Begin Source File
+
SOURCE=.\zend_strtod.h
# End Source File
# Begin Source File
diff --git a/Zend/zend.c b/Zend/zend.c index 53bae4c95f..698992a6e6 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -693,6 +693,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions TS EG(user_exception_handler) = NULL; #endif + zend_interned_strings_init(TSRMLS_C); zend_startup_builtin_functions(TSRMLS_C); zend_register_standard_constants(TSRMLS_C); zend_register_auto_global("GLOBALS", sizeof("GLOBALS") - 1, NULL TSRMLS_CC); @@ -781,6 +782,8 @@ void zend_shutdown(TSRMLS_D) /* {{{ */ GLOBAL_CONSTANTS_TABLE = NULL; #endif zend_destroy_rsrc_list_dtors(); + + zend_interned_strings_dtor(TSRMLS_C); } /* }}} */ diff --git a/Zend/zend.h b/Zend/zend.h index fce65e0337..6348e5997c 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -237,6 +237,7 @@ char *alloca (); #include "zend_alloc.h" #include "zend_types.h" +#include "zend_string.h" #ifdef HAVE_LIMITS_H # include <limits.h> @@ -599,8 +600,8 @@ END_EXTERN_C() /* FIXME: Check if we can save if (ptr) too */ -#define STR_FREE(ptr) if (ptr) { efree(ptr); } -#define STR_FREE_REL(ptr) if (ptr) { efree_rel(ptr); } +#define STR_FREE(ptr) if (ptr && !IS_INTERNED(ptr)) { efree(ptr); } +#define STR_FREE_REL(ptr) if (ptr && !IS_INTERNED(ptr)) { efree_rel(ptr); } #define STR_EMPTY_ALLOC() estrndup("", sizeof("")-1) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index c08e43d35d..a7b73ea017 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1893,10 +1893,10 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio } } fname_len = strlen(ptr->fname); - lowercase_name = zend_str_tolower_dup(ptr->fname, fname_len); + lowercase_name = CG(new_interned_string)(zend_str_tolower_dup(ptr->fname, fname_len), fname_len + 1, 1 TSRMLS_CC); if (zend_hash_add(target_function_table, lowercase_name, fname_len+1, &function, sizeof(zend_function), (void**)®_function) == FAILURE) { unload=1; - efree(lowercase_name); + str_efree(lowercase_name); break; } if (scope) { @@ -1938,7 +1938,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, const zend_functio } ptr++; count++; - efree(lowercase_name); + str_efree(lowercase_name); } if (unload) { /* before unloading, display all remaining bad function in the module */ if (scope) { @@ -2168,7 +2168,7 @@ int zend_next_free_module(void) /* {{{ */ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class_entry, zend_uint ce_flags TSRMLS_DC) /* {{{ */ { zend_class_entry *class_entry = malloc(sizeof(zend_class_entry)); - char *lowercase_name = malloc(orig_class_entry->name_length + 1); + char *lowercase_name = emalloc(orig_class_entry->name_length + 1); *class_entry = *orig_class_entry; class_entry->type = ZEND_INTERNAL_CLASS; @@ -2181,8 +2181,9 @@ static zend_class_entry *do_register_internal_class(zend_class_entry *orig_class } zend_str_tolower_copy(lowercase_name, orig_class_entry->name, class_entry->name_length); + lowercase_name = CG(new_interned_string)(lowercase_name, class_entry->name_length + 1, 1 TSRMLS_CC); zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL); - free(lowercase_name); + str_efree(lowercase_name); return class_entry; } /* }}} */ @@ -3070,6 +3071,7 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in { zend_property_info property_info; HashTable *target_symbol_table; + char *interned_name; if (!(access_type & ZEND_ACC_PPP_MASK)) { access_type |= ZEND_ACC_PUBLIC; @@ -3097,7 +3099,6 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in int priv_name_length; zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS); - zend_hash_update(target_symbol_table, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL); property_info.name = priv_name; property_info.name_length = priv_name_length; } @@ -3107,7 +3108,6 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in int prot_name_length; zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS); - zend_hash_update(target_symbol_table, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL); property_info.name = prot_name; property_info.name_length = prot_name_length; } @@ -3121,11 +3121,27 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, const char *name, in zend_hash_del(target_symbol_table, prot_name, prot_name_length+1); pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS); } - zend_hash_update(target_symbol_table, name, name_length+1, &property, sizeof(zval *), NULL); - property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length); + if (IS_INTERNED(name)) { + property_info.name = (char*)name; + } else { + property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length); + } property_info.name_length = name_length; break; } + + interned_name = CG(new_interned_string)(property_info.name, property_info.name_length+1, 0 TSRMLS_CC); + if (interned_name != property_info.name) { + if (ce->type == ZEND_USER_CLASS) { + efree(property_info.name); + } else { + free(property_info.name); + } + property_info.name = interned_name; + } + + zend_hash_update(target_symbol_table, property_info.name, property_info.name_length+1, &property, sizeof(zval *), NULL); + property_info.flags = access_type; property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1); diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index ce4a1be893..7506401df2 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -681,7 +681,7 @@ repeat: zval_ptr_dtor(&val_free); } c.flags = case_sensitive; /* non persistent */ - c.name = zend_strndup(name, name_len); + c.name = IS_INTERNED(name) ? name : zend_strndup(name, name_len); c.name_len = name_len+1; c.module_number = PHP_USER_CONSTANT; if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) { diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 5a57f8e03f..339d92a9cb 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -73,7 +73,9 @@ ZEND_API zend_executor_globals executor_globals; static void zend_duplicate_property_info(zend_property_info *property_info) /* {{{ */ { - property_info->name = estrndup(property_info->name, property_info->name_length); + if (!IS_INTERNED(property_info->name)) { + property_info->name = estrndup(property_info->name, property_info->name_length); + } if (property_info->doc_comment) { property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len); } @@ -83,14 +85,16 @@ static void zend_duplicate_property_info(zend_property_info *property_info) /* { static void zend_duplicate_property_info_internal(zend_property_info *property_info) /* {{{ */ { - property_info->name = zend_strndup(property_info->name, property_info->name_length); + if (!IS_INTERNED(property_info->name)) { + property_info->name = zend_strndup(property_info->name, property_info->name_length); + } } /* }}} */ static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ */ { - efree(property_info->name); + str_efree(property_info->name); if (property_info->doc_comment) { efree(property_info->doc_comment); } @@ -100,7 +104,7 @@ static void zend_destroy_property_info(zend_property_info *property_info) /* {{{ static void zend_destroy_property_info_internal(zend_property_info *property_info) /* {{{ */ { - free(property_info->name); + str_free(property_info->name); } /* }}} */ @@ -292,17 +296,18 @@ static zend_uint get_temporary_variable(zend_op_array *op_array) /* {{{ */ } /* }}} */ -static int lookup_cv(zend_op_array *op_array, char* name, int name_len) /* {{{ */ +static int lookup_cv(zend_op_array *op_array, char* name, int name_len TSRMLS_DC) /* {{{ */ { int i = 0; ulong hash_value = zend_inline_hash_func(name, name_len+1); while (i < op_array->last_var) { - if (op_array->vars[i].hash_value == hash_value && - op_array->vars[i].name_len == name_len && - strcmp(op_array->vars[i].name, name) == 0) { - efree(name); - return i; + if (op_array->vars[i].name == name || + (op_array->vars[i].hash_value == hash_value && + op_array->vars[i].name_len == name_len && + memcmp(op_array->vars[i].name, name, name_len) == 0)) { + str_efree(name); + return i; } i++; } @@ -312,7 +317,7 @@ static int lookup_cv(zend_op_array *op_array, char* name, int name_len) /* {{{ * op_array->size_var += 16; /* FIXME */ op_array->vars = erealloc(op_array->vars, op_array->size_var*sizeof(zend_compiled_variable)); } - op_array->vars[i].name = name; /* estrndup(name, name_len); */ + op_array->vars[i].name = CG(new_interned_string)(name, name_len + 1, 1 TSRMLS_CC); op_array->vars[i].name_len = name_len; op_array->vars[i].hash_value = hash_value; return i; @@ -338,6 +343,13 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv) /* {{{ */ op_array->size_literal += 16; /* FIXME */ op_array->literals = (zend_literal*)erealloc(op_array->literals, op_array->size_literal * sizeof(zend_literal)); } + if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) { + zval *z = (zval*)zv; + TSRMLS_FETCH(); + + Z_STRVAL_P(z) = + CG(new_interned_string)(Z_STRVAL_P(zv), Z_STRLEN_P(zv) + 1, 1 TSRMLS_CC); + } CONSTANT_EX(op_array, i) = *zv; Z_SET_REFCOUNT(CONSTANT_EX(op_array, i), 2); Z_SET_ISREF(CONSTANT_EX(op_array, i)); @@ -463,7 +475,8 @@ void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar (CG(active_op_array)->last == 0 || CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) { result->op_type = IS_CV; - result->u.op.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len); + result->u.op.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC); + varname->u.constant.value.str.val = CG(active_op_array)->vars[result->u.op.var].name; result->EA = 0; return; } @@ -1078,7 +1091,7 @@ void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS this_var = opline_ptr->result.var; if (CG(active_op_array)->this_var == -1) { - CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(CONSTANT(opline_ptr->op1.constant)), Z_STRLEN(CONSTANT(opline_ptr->op1.constant))); + CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), Z_STRVAL(CONSTANT(opline_ptr->op1.constant)), Z_STRLEN(CONSTANT(opline_ptr->op1.constant)) TSRMLS_CC); Z_TYPE(CONSTANT(opline_ptr->op1.constant)) = IS_NULL; } else { zend_del_literal(CG(active_op_array), opline_ptr->op1.constant); @@ -1090,7 +1103,7 @@ void zend_do_end_variable_parse(znode *variable, int type, int arg_offset TSRMLS variable->u.op.var = CG(active_op_array)->this_var; } } else if (CG(active_op_array)->this_var == -1) { - CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1); + CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), estrndup("this", sizeof("this")-1), sizeof("this")-1 TSRMLS_CC); } } @@ -1290,7 +1303,6 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n } function_token->u.op_array = CG(active_op_array); - lcname = zend_str_tolower_dup(name, name_len); orig_interactive = CG(interactive); CG(interactive) = 0; @@ -1308,6 +1320,8 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n op_array.line_start = zend_get_compiled_lineno(TSRMLS_C); if (is_method) { + lcname = CG(new_interned_string)(zend_str_tolower_dup(name, name_len), name_len + 1, 1 TSRMLS_CC); + if (zend_hash_add(&CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) { zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name); } @@ -1413,7 +1427,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n free_alloca(class_lcname, use_heap); } - efree(lcname); + str_efree(lcname); } else { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); zval key; @@ -1426,9 +1440,10 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n zval_copy_ctor(&tmp.u.constant); zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC); op_array.function_name = Z_STRVAL(tmp.u.constant); - efree(lcname); name_len = Z_STRLEN(tmp.u.constant); lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len); + } else { + lcname = zend_str_tolower_dup(name, name_len); } opline->opcode = ZEND_DECLARE_FUNCTION; @@ -1596,7 +1611,7 @@ void zend_do_receive_arg(zend_uchar op, const znode *var, const znode *offset, c } CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args)); cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1]; - cur_arg_info->name = estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len); + cur_arg_info->name = CG(new_interned_string)(estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len), varname->u.constant.value.str.len + 1, 1 TSRMLS_CC); cur_arg_info->name_len = varname->u.constant.value.str.len; cur_arg_info->array_type_hint = 0; cur_arg_info->allow_null = 1; @@ -1610,6 +1625,7 @@ void zend_do_receive_arg(zend_uchar op, const znode *var, const znode *offset, c if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) { zend_resolve_class_name(class_type, &opline->extended_value, 1 TSRMLS_CC); } + class_type->u.constant.value.str.val = CG(new_interned_string)(class_type->u.constant.value.str.val, class_type->u.constant.value.str.len + 1, 1 TSRMLS_CC); cur_arg_info->class_name = class_type->u.constant.value.str.val; cur_arg_info->class_name_len = class_type->u.constant.value.str.len; if (op == ZEND_RECV_INIT) { @@ -1683,7 +1699,7 @@ zend_error(E_ERROR, "Internal error 1 ???"); lc_name = zend_str_tolower_dup(Z_STRVAL(CONSTANT(literal)), Z_STRLEN(CONSTANT(literal))); ZVAL_STRINGL(&c, lc_name, Z_STRLEN(CONSTANT(literal)), 0); lc_literal = zend_add_literal(CG(active_op_array), &c); - Z_HASH_P(&CONSTANT(lc_literal)) = zend_hash_func(lc_name, Z_STRLEN(CONSTANT(literal))+1); + Z_HASH_P(&CONSTANT(lc_literal)) = zend_hash_func(Z_STRVAL(c), Z_STRLEN(c)+1); if (literal + 1 != lc_literal) { zend_error(E_ERROR, "Internal error 2 ???"); } @@ -1710,7 +1726,7 @@ zend_error(E_ERROR, "Internal error 3 ???"); } ZVAL_STRINGL(&c, lc_name, lc_len, 0); lc_literal = zend_add_literal(CG(active_op_array), &c); - Z_HASH_P(&CONSTANT(lc_literal)) = zend_hash_func(lc_name, lc_len+1); + Z_HASH_P(&CONSTANT(lc_literal)) = zend_hash_func(Z_STRVAL(c), Z_STRLEN(c)+1); if (literal + 1 != lc_literal) { zend_error(E_ERROR, "Internal error 4 ???"); } @@ -2476,7 +2492,7 @@ void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */ } /* }}} */ -void zend_do_begin_catch(znode *try_token, znode *class_name, const znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */ +void zend_do_begin_catch(znode *try_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */ { long catch_op_number; zend_op *opline; @@ -2500,7 +2516,8 @@ void zend_do_begin_catch(znode *try_token, znode *class_name, const znode *catch opline->opcode = ZEND_CATCH; SET_NODE(opline->op1, &catch_class); opline->op2_type = IS_CV; - opline->op2.var = lookup_cv(CG(active_op_array), catch_var->u.constant.value.str.val, catch_var->u.constant.value.str.len); + opline->op2.var = lookup_cv(CG(active_op_array), catch_var->u.constant.value.str.val, catch_var->u.constant.value.str.len TSRMLS_CC); + catch_var->u.constant.value.str.val = CG(active_op_array)->vars[opline->op2.var].name; opline->result.num = 0; /* 1 means it's the last catch in the block */ try_token->u.op.opline_num = catch_op_number; @@ -3806,7 +3823,7 @@ void zend_do_declare_property(const znode *var_name, const znode *value, zend_ui CG(doc_comment_len) = 0; } - zend_declare_property_ex(CG(active_class_entry), var_name->u.constant.value.str.val, var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC); + zend_declare_property_ex(CG(active_class_entry), CG(new_interned_string)(var_name->u.constant.value.str.val, var_name->u.constant.value.str.len + 1, 0 TSRMLS_CC), var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC); efree(var_name->u.constant.value.str.val); } /* }}} */ @@ -3822,7 +3839,7 @@ void zend_do_declare_class_constant(znode *var_name, const znode *value TSRMLS_D ALLOC_ZVAL(property); *property = value->u.constant; - if (zend_hash_add(&CG(active_class_entry)->constants_table, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL)==FAILURE) { + if (zend_hash_add(&CG(active_class_entry)->constants_table, CG(new_interned_string)(var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, 0 TSRMLS_CC), var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL)==FAILURE) { FREE_ZVAL(property); zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val); } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index b7185c7fcc..33e60aeb06 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -456,7 +456,7 @@ void zend_do_begin_lambda_function_declaration(znode *result, znode *function_to void zend_do_fetch_lexical_variable(znode *varname, zend_bool is_ref TSRMLS_DC); void zend_do_try(znode *try_token TSRMLS_DC); -void zend_do_begin_catch(znode *try_token, znode *catch_class, const znode *catch_var, znode *first_catch TSRMLS_DC); +void zend_do_begin_catch(znode *try_token, znode *catch_class, znode *catch_var, znode *first_catch TSRMLS_DC); void zend_do_end_catch(const znode *try_token TSRMLS_DC); void zend_do_throw(const znode *expr TSRMLS_DC); diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index 0543903e84..1743ffd2a8 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -32,13 +32,15 @@ void free_zend_constant(zend_constant *c) if (!(c->flags & CONST_PERSISTENT)) { zval_dtor(&c->value); } - free(c->name); + str_free(c->name); } void copy_zend_constant(zend_constant *c) { - c->name = zend_strndup(c->name, c->name_len - 1); + if (!IS_INTERNED(c->name)) { + c->name = zend_strndup(c->name, c->name_len - 1); + } if (!(c->flags & CONST_PERSISTENT)) { zval_copy_ctor(&c->value); } @@ -422,12 +424,14 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC) /* keep in mind that c->name_len already contains the '\0' */ lowercase_name = estrndup(c->name, c->name_len-1); zend_str_tolower(lowercase_name, c->name_len-1); + lowercase_name = CG(new_interned_string)(lowercase_name, c->name_len, 1 TSRMLS_CC); name = lowercase_name; } else { char *slash = strrchr(c->name, '\\'); if(slash) { lowercase_name = estrndup(c->name, c->name_len-1); zend_str_tolower(lowercase_name, slash-c->name); + lowercase_name = CG(new_interned_string)(lowercase_name, c->name_len, 1 TSRMLS_CC); name = lowercase_name; } else { name = c->name; @@ -437,13 +441,13 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC) if ((strncmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) || zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) { zend_error(E_NOTICE,"Constant %s already defined", name); - free(c->name); + str_free(c->name); if (!(c->flags & CONST_PERSISTENT)) { zval_dtor(&c->value); } ret = FAILURE; } - if (lowercase_name) { + if (lowercase_name && !IS_INTERNED(lowercase_name)) { efree(lowercase_name); } return ret; diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index f941167ea9..7966ed144c 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -610,12 +610,24 @@ static inline int zend_assign_to_string_offset(const temp_variable *T, const zva } if (T->str_offset.offset >= Z_STRLEN_P(T->str_offset.str)) { - Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1); + if (IS_INTERNED(Z_STRVAL_P(T->str_offset.str))) { + char *tmp = (char *) emalloc(T->str_offset.offset+1+1); + + memcpy(tmp, Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1); + Z_STRVAL_P(T->str_offset.str) = tmp; + } else { + Z_STRVAL_P(T->str_offset.str) = (char *) erealloc(Z_STRVAL_P(T->str_offset.str), T->str_offset.offset+1+1); + } memset(Z_STRVAL_P(T->str_offset.str) + Z_STRLEN_P(T->str_offset.str), ' ', T->str_offset.offset - Z_STRLEN_P(T->str_offset.str)); Z_STRVAL_P(T->str_offset.str)[T->str_offset.offset+1] = 0; Z_STRLEN_P(T->str_offset.str) = T->str_offset.offset+1; + } else if (IS_INTERNED(Z_STRVAL_P(T->str_offset.str))) { + char *tmp = (char *) emalloc(Z_STRLEN_P(T->str_offset.str) + 1); + + memcpy(tmp, Z_STRVAL_P(T->str_offset.str), Z_STRLEN_P(T->str_offset.str) + 1); + Z_STRVAL_P(T->str_offset.str) = tmp; } if (Z_TYPE_P(value) != IS_STRING) { @@ -803,7 +815,11 @@ static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, const zva hval = Z_HASH_P(dim); } else { ZEND_HANDLE_NUMERIC_EX(offset_key, offset_key_length+1, index, goto num_index); - hval = zend_hash_func(offset_key, offset_key_length+1); + if (IS_INTERNED(offset_key)) { + hval = INTERNED_HASH(offset_key); + } else { + hval = zend_hash_func(offset_key, offset_key_length+1); + } } fetch_string_dim: if (zend_hash_quick_find(ht, offset_key, offset_key_length+1, hval, (void **) &retval) == FAILURE) { diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index d0ce7f1bf4..fd4fb928e4 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -525,7 +525,7 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco Z_STRLEN_P(p) -= ((colon - Z_STRVAL_P(p)) + 1); if (inline_change) { colon = estrndup(colon, Z_STRLEN_P(p)); - efree(Z_STRVAL_P(p)); + str_efree(Z_STRVAL_P(p)); Z_STRVAL_P(p) = colon; } else { Z_STRVAL_P(p) = colon + 1; @@ -561,12 +561,12 @@ ZEND_API int zval_update_constant_ex(zval **pp, void *arg, zend_class_entry *sco if (fix_save) { save--; } - if (inline_change) { + if (inline_change && !IS_INTERNED(save)) { efree(save); } save = NULL; } - if (inline_change && save && save != actual) { + if (inline_change && save && save != actual && !IS_INTERNED(save)) { efree(save); } zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", actual, actual); diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index 368e88ec39..19be67d1de 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -140,6 +140,18 @@ struct _zend_compiler_globals { HashTable *labels; zend_stack labels_stack; + /* interned strings */ + char *interned_strings_start; + char *interned_strings_end; + char *interned_strings_top; + char *interned_strings_snapshot_top; + + HashTable interned_strings; + + char *(*new_interned_string)(char *str, int len, int free_src TSRMLS_DC); + void (*interned_strings_snapshot)(TSRMLS_D); + void (*interned_strings_restore)(TSRMLS_D); + #ifdef ZEND_MULTIBYTE zend_encoding **script_encoding_list; size_t script_encoding_list_size; diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 69b6bdc169..530afa7d34 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -20,6 +20,7 @@ /* $Id$ */ #include "zend.h" +#include "zend_globals.h" #define CONNECT_TO_BUCKET_DLLIST(element, list_head) \ (element)->pNext = (list_head); \ @@ -210,8 +211,8 @@ ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKe p = ht->arBuckets[nIndex]; while (p != NULL) { - if ((p->h == h) && (p->nKeyLength == nKeyLength)) { - if (!memcmp(p->arKey, arKey, nKeyLength)) { + if (p->arKey == arKey || + ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) { if (flag & HASH_ADD) { return FAILURE; } @@ -232,16 +233,24 @@ ZEND_API int _zend_hash_add_or_update(HashTable *ht, const char *arKey, uint nKe } HANDLE_UNBLOCK_INTERRUPTIONS(); return SUCCESS; - } } p = p->pNext; } - p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent); - if (!p) { - return FAILURE; + if (IS_INTERNED(arKey)) { + p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent); + if (!p) { + return FAILURE; + } + p->arKey = (char*)arKey; + } else { + p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent); + if (!p) { + return FAILURE; + } + p->arKey = (char*)(p + 1); + memcpy(p->arKey, arKey, nKeyLength); } - memcpy(p->arKey, arKey, nKeyLength); p->nKeyLength = nKeyLength; INIT_DATA(ht, p, pData, nDataSize); p->h = h; @@ -276,8 +285,8 @@ ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, ui p = ht->arBuckets[nIndex]; while (p != NULL) { - if ((p->h == h) && (p->nKeyLength == nKeyLength)) { - if (!memcmp(p->arKey, arKey, nKeyLength)) { + if (p->arKey == arKey || + ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) { if (flag & HASH_ADD) { return FAILURE; } @@ -298,17 +307,25 @@ ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, const char *arKey, ui } HANDLE_UNBLOCK_INTERRUPTIONS(); return SUCCESS; - } } p = p->pNext; } - p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent); - if (!p) { - return FAILURE; + if (IS_INTERNED(arKey)) { + p = (Bucket *) pemalloc(sizeof(Bucket), ht->persistent); + if (!p) { + return FAILURE; + } + p->arKey = (char*)arKey; + } else { + p = (Bucket *) pemalloc(sizeof(Bucket) + nKeyLength, ht->persistent); + if (!p) { + return FAILURE; + } + p->arKey = (char*)(p + 1); + memcpy(p->arKey, arKey, nKeyLength); } - memcpy(p->arKey, arKey, nKeyLength); p->nKeyLength = nKeyLength; INIT_DATA(ht, p, pData, nDataSize); p->h = h; @@ -380,10 +397,11 @@ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void } p = p->pNext; } - p = (Bucket *) pemalloc_rel(sizeof(Bucket) - 1, ht->persistent); + p = (Bucket *) pemalloc_rel(sizeof(Bucket), ht->persistent); if (!p) { return FAILURE; } + p->arKey = NULL; p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */ p->h = h; INIT_DATA(ht, p, pData, nDataSize); @@ -885,11 +903,10 @@ ZEND_API int zend_hash_find(const HashTable *ht, const char *arKey, uint nKeyLen p = ht->arBuckets[nIndex]; while (p != NULL) { - if ((p->h == h) && (p->nKeyLength == nKeyLength)) { - if (!memcmp(p->arKey, arKey, nKeyLength)) { + if (p->arKey == arKey || + ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) { *pData = p->pData; return SUCCESS; - } } p = p->pNext; } @@ -912,11 +929,10 @@ ZEND_API int zend_hash_quick_find(const HashTable *ht, const char *arKey, uint n p = ht->arBuckets[nIndex]; while (p != NULL) { - if ((p->h == h) && (p->nKeyLength == nKeyLength)) { - if (!memcmp(p->arKey, arKey, nKeyLength)) { + if (p->arKey == arKey || + ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) { *pData = p->pData; return SUCCESS; - } } p = p->pNext; } @@ -937,10 +953,9 @@ ZEND_API int zend_hash_exists(const HashTable *ht, const char *arKey, uint nKeyL p = ht->arBuckets[nIndex]; while (p != NULL) { - if ((p->h == h) && (p->nKeyLength == nKeyLength)) { - if (!memcmp(p->arKey, arKey, nKeyLength)) { + if (p->arKey == arKey || + ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) { return 1; - } } p = p->pNext; } @@ -963,10 +978,9 @@ ZEND_API int zend_hash_quick_exists(const HashTable *ht, const char *arKey, uint p = ht->arBuckets[nIndex]; while (p != NULL) { - if ((p->h == h) && (p->nKeyLength == nKeyLength)) { - if (!memcmp(p->arKey, arKey, nKeyLength)) { + if (p->arKey == arKey || + ((p->h == h) && (p->nKeyLength == nKeyLength) && !memcmp(p->arKey, arKey, nKeyLength))) { return 1; - } } p = p->pNext; } @@ -1290,7 +1304,7 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const } if (p->nKeyLength != str_length) { - Bucket *q = (Bucket *) pemalloc(sizeof(Bucket) - 1 + str_length, ht->persistent); + Bucket *q = (Bucket *) pemalloc(sizeof(Bucket) + str_length, ht->persistent); q->nKeyLength = str_length; if (p->pData == &p->pDataPtr) { @@ -1324,6 +1338,7 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, const if (key_type == HASH_KEY_IS_LONG) { p->h = num_index; } else { + p->arKey = (char*)(p+1); memcpy(p->arKey, str_index, str_length); p->h = zend_inline_hash_func(str_index, str_length); } diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index b26e0dbd6a..39a75fd1d4 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -60,7 +60,7 @@ typedef struct bucket { struct bucket *pListLast; struct bucket *pNext; struct bucket *pLast; - char arKey[1]; /* Must be last element */ + char *arKey; } Bucket; typedef struct _hashtable { diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index a4faff3825..2857c87368 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -408,7 +408,13 @@ zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC) ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC) { /* enforce two trailing NULLs for flex... */ - str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD); + if (IS_INTERNED(str->value.str.val)) { + char *tmp = safe_emalloc(1, str->value.str.len, ZEND_MMAP_AHEAD); + memcpy(tmp, str->value.str.val, str->value.str.len + ZEND_MMAP_AHEAD); + str->value.str.val = tmp; + } else { + str->value.str.val = safe_erealloc(str->value.str.val, 1, str->value.str.len, ZEND_MMAP_AHEAD); + } memset(str->value.str.val + str->value.str.len, 0, ZEND_MMAP_AHEAD); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 9fdbd70870..9e9b2f5767 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -243,7 +243,7 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) i = op_array->last_var; while (i > 0) { i--; - efree(op_array->vars[i].name); + str_efree(op_array->vars[i].name); } efree(op_array->vars); } @@ -275,8 +275,8 @@ ZEND_API void destroy_op_array(zend_op_array *op_array TSRMLS_DC) } if (op_array->arg_info) { for (i=0; i<op_array->num_args; i++) { - efree((char*)op_array->arg_info[i].name); - if (op_array->arg_info[i].class_name) { + str_efree((char*)op_array->arg_info[i].name); + if (op_array->arg_info[i].class_name && !IS_INTERNED(op_array->arg_info[i].class_name)) { efree((char*)op_array->arg_info[i].class_name); } } diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 8af1edee50..abc7489dbf 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -1177,11 +1177,18 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* must support result==op1 */ ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */ { - Z_STRLEN_P(result) = Z_STRLEN_P(op1) + 1; - Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), Z_STRLEN_P(result)+1); - Z_STRVAL_P(result)[Z_STRLEN_P(result) - 1] = (char) Z_LVAL_P(op2); - Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0; - Z_TYPE_P(result) = IS_STRING; + int length = Z_STRLEN_P(op1) + 1; + char *buf; + + if (IS_INTERNED(Z_STRVAL_P(op1))) { + buf = (char *) emalloc(length + 1); + memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1)); + } else { + buf = (char *) erealloc(Z_STRVAL_P(op1), length + 1); + } + buf[length - 1] = (char) Z_LVAL_P(op2); + buf[length] = 0; + ZVAL_STRINGL(result, buf, length, 0); return SUCCESS; } /* }}} */ @@ -1190,12 +1197,17 @@ ZEND_API int add_char_to_string(zval *result, const zval *op1, const zval *op2) ZEND_API int add_string_to_string(zval *result, const zval *op1, const zval *op2) /* {{{ */ { int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); + char *buf; - Z_STRVAL_P(result) = (char *) erealloc(Z_STRVAL_P(op1), length+1); - memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); - Z_STRVAL_P(result)[length] = 0; - Z_STRLEN_P(result) = length; - Z_TYPE_P(result) = IS_STRING; + if (IS_INTERNED(Z_STRVAL_P(op1))) { + buf = (char *) emalloc(length+1); + memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1)); + } else { + buf = (char *) erealloc(Z_STRVAL_P(op1), length+1); + } + memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); + buf[length] = 0; + ZVAL_STRINGL(result, buf, length, 0); return SUCCESS; } /* }}} */ @@ -1224,7 +1236,7 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{ if (use_copy2) { op2 = &op2_copy; } - if (result==op1) { /* special case, perform operations on result */ + if (result==op1 && !IS_INTERNED(Z_STRVAL_P(op1))) { /* special case, perform operations on result */ uint res_len = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); if (Z_STRLEN_P(result) < 0 || (int) (Z_STRLEN_P(op1) + Z_STRLEN_P(op2)) < 0) { @@ -1239,12 +1251,13 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC) /* {{ Z_STRVAL_P(result)[res_len]=0; Z_STRLEN_P(result) = res_len; } else { - Z_STRLEN_P(result) = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); - Z_STRVAL_P(result) = (char *) emalloc(Z_STRLEN_P(result) + 1); - memcpy(Z_STRVAL_P(result), Z_STRVAL_P(op1), Z_STRLEN_P(op1)); - memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); - Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0; - Z_TYPE_P(result) = IS_STRING; + int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2); + char *buf = (char *) emalloc(length + 1); + + memcpy(buf, Z_STRVAL_P(op1), Z_STRLEN_P(op1)); + memcpy(buf + Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2)); + buf[length] = 0; + ZVAL_STRINGL(result, buf, length, 0); } if (use_copy1) { zval_dtor(op1); @@ -1668,6 +1681,12 @@ static void increment_string(zval *str) /* {{{ */ return; } + if (IS_INTERNED(s)) { + s = (char*) emalloc(Z_STRLEN_P(str) + 1); + memcpy(s, Z_STRVAL_P(str), Z_STRLEN_P(str) + 1); + Z_STRVAL_P(str) = s; + } + while (pos >= 0) { ch = s[pos]; if (ch >= 'a' && ch <= 'z') { @@ -1753,7 +1772,7 @@ ZEND_API int increment_function(zval *op1) /* {{{ */ switch (is_numeric_string(Z_STRVAL_P(op1), Z_STRLEN_P(op1), &lval, &dval, 0)) { case IS_LONG: - efree(Z_STRVAL_P(op1)); + str_efree(Z_STRVAL_P(op1)); if (lval == LONG_MAX) { /* switch to double */ double d = (double)lval; @@ -1763,7 +1782,7 @@ ZEND_API int increment_function(zval *op1) /* {{{ */ } break; case IS_DOUBLE: - efree(Z_STRVAL_P(op1)); + str_efree(Z_STRVAL_P(op1)); ZVAL_DOUBLE(op1, dval+1); break; default: @@ -1879,6 +1898,9 @@ ZEND_API int zend_binary_strcmp(const char *s1, uint len1, const char *s2, uint { int retval; + if (s1 == s2) { + return 0; + } retval = memcmp(s1, s2, MIN(len1, len2)); if (!retval) { return (len1 - len2); @@ -1892,6 +1914,9 @@ ZEND_API int zend_binary_strncmp(const char *s1, uint len1, const char *s2, uint { int retval; + if (s1 == s2) { + return 0; + } retval = memcmp(s1, s2, MIN(length, MIN(len1, len2))); if (!retval) { return (MIN(length, len1) - MIN(length, len2)); @@ -1906,8 +1931,11 @@ ZEND_API int zend_binary_strcasecmp(const char *s1, uint len1, const char *s2, u int len; int c1, c2; - len = MIN(len1, len2); + if (s1 == s2) { + return 0; + } + len = MIN(len1, len2); while (len--) { c1 = zend_tolower((int)*(unsigned char *)s1++); c2 = zend_tolower((int)*(unsigned char *)s2++); @@ -1925,8 +1953,10 @@ ZEND_API int zend_binary_strncasecmp(const char *s1, uint len1, const char *s2, int len; int c1, c2; + if (s1 == s2) { + return 0; + } len = MIN(length, MIN(len1, len2)); - while (len--) { c1 = zend_tolower((int)*(unsigned char *)s1++); c2 = zend_tolower((int)*(unsigned char *)s2++); diff --git a/Zend/zend_string.c b/Zend/zend_string.c new file mode 100644 index 0000000000..098ad62713 --- /dev/null +++ b/Zend/zend_string.c @@ -0,0 +1,229 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2010 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Dmitry Stogov <dmitry@zend.com> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: $ */ + +#include "zend.h" +#include "zend_globals.h" + +#ifndef ZEND_DEBUG_INTERNED_STRINGS +# define ZEND_DEBUG_INTERNED_STRINGS 0 +#endif + +#if ZEND_DEBUG_INTERNED_STRINGS +# include <sys/mman.h> +#endif + +static char *zend_new_interned_string(char *str, int len, int free_src TSRMLS_DC); +static void zend_interned_strings_snapshot(TSRMLS_D); +static void zend_interned_strings_restore(TSRMLS_D); + +void zend_interned_strings_init(TSRMLS_D) +{ +#ifndef ZTS + size_t size = 1024 * 1024; + +#if ZEND_DEBUG_INTERNED_STRINGS + CG(interned_strings_start) = valloc(size); +#else + CG(interned_strings_start) = malloc(size); +#endif + + CG(interned_strings_top) = CG(interned_strings_start); + CG(interned_strings_snapshot_top) = CG(interned_strings_start); + CG(interned_strings_end) = CG(interned_strings_start) + size; + + zend_hash_init(&CG(interned_strings), 0, NULL, NULL, 1); + + CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1; + CG(interned_strings).arBuckets = (Bucket **) pecalloc(CG(interned_strings).nTableSize, sizeof(Bucket *), CG(interned_strings).persistent); + +#if ZEND_DEBUG_INTERNED_STRINGS + mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ); +#endif + +#endif + + CG(new_interned_string) = zend_new_interned_string; + CG(interned_strings_snapshot) = zend_interned_strings_snapshot; + CG(interned_strings_restore) = zend_interned_strings_restore; +} + +void zend_interned_strings_dtor(TSRMLS_D) +{ +#ifndef ZTS +#if ZEND_DEBUG_INTERNED_STRINGS + mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ); +#endif + free(CG(interned_strings).arBuckets); + free(CG(interned_strings_start)); +#endif +} + +static char *zend_new_interned_string(char *arKey, int nKeyLength, int free_src TSRMLS_DC) +{ +#ifndef ZTS + ulong h; + uint nIndex; + Bucket *p; + + if (IS_INTERNED(arKey)) { + return arKey; + } + + h = zend_inline_hash_func(arKey, nKeyLength); + nIndex = h & CG(interned_strings).nTableMask; + p = CG(interned_strings).arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && (p->nKeyLength == nKeyLength)) { + if (!memcmp(p->arKey, arKey, nKeyLength)) { + if (free_src) { + efree(arKey); + } + return p->arKey; + } + } + p = p->pNext; + } + + if (CG(interned_strings_top) + ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength) >= + CG(interned_strings_end)) { + /* no memory */ + return arKey; + } + + p = (Bucket *) CG(interned_strings_top); + CG(interned_strings_top) += ZEND_MM_ALIGNED_SIZE(sizeof(Bucket) + nKeyLength); + +#if ZEND_DEBUG_INTERNED_STRINGS + mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ | PROT_WRITE); +#endif + + p->arKey = (char*)(p+1); + memcpy(p->arKey, arKey, nKeyLength); + if (free_src) { + efree(arKey); + } + p->nKeyLength = nKeyLength; + p->h = h; + p->pData = &p->pDataPtr; + p->pDataPtr = p; + + p->pNext = CG(interned_strings).arBuckets[nIndex]; + p->pLast = NULL; + if (p->pNext) { + p->pNext->pLast = p; + } + + HANDLE_BLOCK_INTERRUPTIONS(); + + p->pListLast = CG(interned_strings).pListTail; + CG(interned_strings).pListTail = p; + p->pListNext = NULL; + if (p->pListLast != NULL) { + p->pListLast->pListNext = p; + } + if (!CG(interned_strings).pListHead) { + CG(interned_strings).pListHead = p; + } + + CG(interned_strings).arBuckets[nIndex] = p; + + HANDLE_UNBLOCK_INTERRUPTIONS(); + + CG(interned_strings).nNumOfElements++; + + if (CG(interned_strings).nNumOfElements > CG(interned_strings).nTableSize) { + if ((CG(interned_strings).nTableSize << 1) > 0) { /* Let's double the table size */ + Bucket **t = (Bucket **) perealloc_recoverable(CG(interned_strings).arBuckets, (CG(interned_strings).nTableSize << 1) * sizeof(Bucket *), CG(interned_strings).persistent); + + if (t) { + HANDLE_BLOCK_INTERRUPTIONS(); + CG(interned_strings).arBuckets = t; + CG(interned_strings).nTableSize = (CG(interned_strings).nTableSize << 1); + CG(interned_strings).nTableMask = CG(interned_strings).nTableSize - 1; + zend_hash_rehash(&CG(interned_strings)); + HANDLE_UNBLOCK_INTERRUPTIONS(); + } + } + } + +#if ZEND_DEBUG_INTERNED_STRINGS + mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ); +#endif + + return p->arKey; +#else + return arKey; +#endif +} + +static void zend_interned_strings_snapshot(TSRMLS_D) +{ + CG(interned_strings_snapshot_top) = CG(interned_strings_top); +} + +static void zend_interned_strings_restore(TSRMLS_D) +{ +#ifndef ZTS + Bucket *p; + int i; +#endif + + CG(interned_strings_top) = CG(interned_strings_snapshot_top); + +#ifndef ZTS +#if ZEND_DEBUG_INTERNED_STRINGS + mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_WRITE | PROT_READ); +#endif + + for (i = 0; i < CG(interned_strings).nTableSize; i++) { + p = CG(interned_strings).arBuckets[i]; + while (p && p->arKey > CG(interned_strings_top)) { + CG(interned_strings).nNumOfElements--; + if (p->pListLast != NULL) { + p->pListLast->pListNext = p->pListNext; + } else { + CG(interned_strings).pListHead = p->pListNext; + } + if (p->pListNext != NULL) { + p->pListNext->pListLast = p->pListLast; + } else { + CG(interned_strings).pListTail = p->pListLast; + } + p = p->pNext; + } + if (p) { + p->pLast = NULL; + } + CG(interned_strings).arBuckets[i] = p; + } + +#if ZEND_DEBUG_INTERNED_STRINGS + mprotect(CG(interned_strings_start), CG(interned_strings_end) - CG(interned_strings_start), PROT_READ); +#endif +#endif +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ diff --git a/Zend/zend_string.h b/Zend/zend_string.h new file mode 100644 index 0000000000..158efceeb8 --- /dev/null +++ b/Zend/zend_string.h @@ -0,0 +1,67 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2010 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@zend.com so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Dmitry Stogov <dmitry@zend.com> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: $ */ + +#ifndef ZEND_STRING_H +#define ZEND_STRING_H + +#include "zend.h" + +void zend_interned_strings_init(TSRMLS_D); +void zend_interned_strings_dtor(TSRMLS_D); + +#ifndef ZTS + +#define IS_INTERNED(s) \ + (((s) >= CG(interned_strings_start)) && ((s) < CG(interned_strings_end))) + +#else + +#define IS_INTERNED(s) \ + (0) + +#endif + +#define INTERNED_LEN(s) \ + (((Bucket*)(((char*)(s))-sizeof(Bucket)))->nKeyLength) + +#define INTERNED_HASH(s) \ + (((Bucket*)(((char*)(s))-sizeof(Bucket)))->h) + +#define str_efree(s) do { \ + if (!IS_INTERNED(s)) { \ + efree(s); \ + } \ + } while (0) + +#define str_free(s) do { \ + if (!IS_INTERNED(s)) { \ + free(s); \ + } \ + } while (0) + +#endif /* ZEND_STRING_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c index dce98ba22c..47f2462761 100644 --- a/Zend/zend_variables.c +++ b/Zend/zend_variables.c @@ -77,7 +77,7 @@ ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC) case IS_STRING: case IS_CONSTANT: CHECK_ZVAL_STRING_REL(zvalue); - free(zvalue->value.str.val); + str_free(zvalue->value.str.val); break; case IS_ARRAY: case IS_CONSTANT_ARRAY: @@ -117,7 +117,9 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC) case IS_CONSTANT: case IS_STRING: CHECK_ZVAL_STRING_REL(zvalue); - zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len); + if (!IS_INTERNED(zvalue->value.str.val)) { + zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len); + } break; case IS_ARRAY: case IS_CONSTANT_ARRAY: { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 0fe828d3dd..735c9daaa8 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -951,6 +951,8 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type */ if (OP1_TYPE == IS_CONST) { hash_value = Z_HASH_P(varname); + } else if (IS_INTERNED(Z_STRVAL_P(varname))) { + hash_value = INTERNED_HASH(Z_STRVAL_P(varname)); } else { hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1); } @@ -3115,7 +3117,11 @@ ZEND_VM_C_LABEL(num_index): hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, ZEND_VM_C_GOTO(num_index)); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -3459,7 +3465,11 @@ ZEND_VM_C_LABEL(num_index_dim): hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, ZEND_VM_C_GOTO(num_index_dim)); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -3967,7 +3977,11 @@ ZEND_VM_C_LABEL(num_index_prop): if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, ZEND_VM_C_GOTO(num_index_prop)); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -4419,7 +4433,7 @@ ZEND_VM_HANDLER(143, ZEND_DECLARE_CONST, CONST, CONST) zval_copy_ctor(&c.value); } c.flags = CONST_CS; /* non persistent, case sensetive */ - c.name = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + c.name = IS_INTERNED(Z_STRVAL_P(name)) ? Z_STRVAL_P(name) : zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); c.name_len = Z_STRLEN_P(name)+1; c.module_number = PHP_USER_CONSTANT; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 26434e5c6c..3650dfac24 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1367,6 +1367,8 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST(int type, ZEND */ if (IS_CONST == IS_CONST) { hash_value = Z_HASH_P(varname); + } else if (IS_INTERNED(Z_STRVAL_P(varname))) { + hash_value = INTERNED_HASH(Z_STRVAL_P(varname)); } else { hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1); } @@ -2889,7 +2891,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -2951,7 +2957,7 @@ static int ZEND_FASTCALL ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER(ZEND_OPCOD zval_copy_ctor(&c.value); } c.flags = CONST_CS; /* non persistent, case sensetive */ - c.name = zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); + c.name = IS_INTERNED(Z_STRVAL_P(name)) ? Z_STRVAL_P(name) : zend_strndup(Z_STRVAL_P(name), Z_STRLEN_P(name)); c.name_len = Z_STRLEN_P(name)+1; c.module_number = PHP_USER_CONSTANT; @@ -3399,7 +3405,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -3875,7 +3885,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -4075,7 +4089,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -4565,7 +4583,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -4685,6 +4707,8 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMP(int type, ZEND_O */ if (IS_TMP_VAR == IS_CONST) { hash_value = Z_HASH_P(varname); + } else if (IS_INTERNED(Z_STRVAL_P(varname))) { + hash_value = INTERNED_HASH(Z_STRVAL_P(varname)); } else { hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1); } @@ -6175,7 +6199,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -6651,7 +6679,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -7127,7 +7159,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -7230,7 +7266,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -7703,7 +7743,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -7981,6 +8025,8 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_VAR(int type, ZEND_O */ if (IS_VAR == IS_CONST) { hash_value = Z_HASH_P(varname); + } else if (IS_INTERNED(Z_STRVAL_P(varname))) { + hash_value = INTERNED_HASH(Z_STRVAL_P(varname)); } else { hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1); } @@ -10759,7 +10805,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -10834,7 +10884,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -10974,7 +11028,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -12528,7 +12586,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -12603,7 +12665,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -12743,7 +12809,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -14348,7 +14418,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -14423,7 +14497,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -14563,7 +14641,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -15230,7 +15312,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -16764,7 +16850,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -16839,7 +16929,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -16979,7 +17073,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -18041,7 +18139,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -18179,7 +18281,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -19108,7 +19214,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -19246,7 +19356,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -20175,7 +20289,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -20313,7 +20431,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -21501,7 +21623,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -21639,7 +21765,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -21975,6 +22105,8 @@ static int ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV(int type, ZEND_OP */ if (IS_CV == IS_CONST) { hash_value = Z_HASH_P(varname); + } else if (IS_INTERNED(Z_STRVAL_P(varname))) { + hash_value = INTERNED_HASH(Z_STRVAL_P(varname)); } else { hash_value = zend_hash_func(Z_STRVAL_P(varname), Z_STRLEN_P(varname)+1); } @@ -24436,7 +24568,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -24511,7 +24647,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -24649,7 +24789,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -26096,7 +26240,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -26171,7 +26319,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -26309,7 +26461,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -27806,7 +27962,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -27881,7 +28041,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -28019,7 +28183,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; @@ -28585,7 +28753,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -30013,7 +30185,11 @@ num_index: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } zend_hash_quick_update(Z_ARRVAL_P(array_ptr), Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, &expr_ptr, sizeof(zval *), NULL); break; @@ -30088,7 +30264,11 @@ num_index_dim: hval = Z_HASH_P(offset); } else { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_dim); - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval) == SUCCESS && ht == &EG(symbol_table)) { @@ -30226,7 +30406,11 @@ num_index_prop: if (!prop_dim) { ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, index, goto num_index_prop); } - hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + if (IS_INTERNED(Z_STRVAL_P(offset))) { + hval = INTERNED_HASH(Z_STRVAL_P(offset)); + } else { + hval = zend_hash_func(Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1); + } } if (zend_hash_quick_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, hval, (void **) &value) == SUCCESS) { isset = 1; diff --git a/configure.in b/configure.in index 230d93fbc6..d88cf11897 100644 --- a/configure.in +++ b/configure.in @@ -1424,7 +1424,7 @@ PHP_ADD_SOURCES(Zend, \ zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \ zend_ini.c zend_qsort.c zend_multibyte.c zend_ts_hash.c zend_stream.c \ zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \ - zend_closures.c zend_float.c) + zend_closures.c zend_float.c zend_string.c) if test -r "$abs_srcdir/Zend/zend_objects.c"; then PHP_ADD_SOURCES(Zend, zend_objects.c zend_object_handlers.c zend_objects_API.c zend_default_classes.c) diff --git a/ext/filter/sanitizing_filters.c b/ext/filter/sanitizing_filters.c index c44d7a8e55..d54ced2f4b 100644 --- a/ext/filter/sanitizing_filters.c +++ b/ext/filter/sanitizing_filters.c @@ -51,7 +51,7 @@ static void php_filter_encode_html(zval *value, const unsigned char *chars) } smart_str_0(&str); - efree(Z_STRVAL_P(value)); + str_efree(Z_STRVAL_P(value)); Z_STRVAL_P(value) = str.c; Z_STRLEN_P(value) = str.len; } @@ -102,7 +102,7 @@ static void php_filter_encode_url(zval *value, const unsigned char* chars, const s++; } *p = '\0'; - efree(Z_STRVAL_P(value)); + str_efree(Z_STRVAL_P(value)); Z_STRVAL_P(value) = (char *)str; Z_STRLEN_P(value) = p - str; } @@ -131,7 +131,7 @@ static void php_filter_strip(zval *value, long flags) } /* update zval string data */ buf[c] = '\0'; - efree(Z_STRVAL_P(value)); + str_efree(Z_STRVAL_P(value)); Z_STRVAL_P(value) = (char *)buf; Z_STRLEN_P(value) = c; } @@ -169,7 +169,7 @@ static void filter_map_apply(zval *value, filter_map *map) } /* update zval string data */ buf[c] = '\0'; - efree(Z_STRVAL_P(value)); + str_efree(Z_STRVAL_P(value)); Z_STRVAL_P(value) = (char *)buf; Z_STRLEN_P(value) = c; } @@ -254,7 +254,7 @@ void php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL) quotes = ENT_NOQUOTES; } buf = php_escape_html_entities_ex(Z_STRVAL_P(value), Z_STRLEN_P(value), &len, 1, quotes, SG(default_charset), 0 TSRMLS_CC); - efree(Z_STRVAL_P(value)); + str_efree(Z_STRVAL_P(value)); Z_STRVAL_P(value) = buf; Z_STRLEN_P(value) = len; } @@ -365,7 +365,7 @@ void php_filter_magic_quotes(PHP_INPUT_FILTER_PARAM_DECL) /* just call php_addslashes quotes */ buf = php_addslashes(Z_STRVAL_P(value), Z_STRLEN_P(value), &len, 0 TSRMLS_CC); - efree(Z_STRVAL_P(value)); + str_efree(Z_STRVAL_P(value)); Z_STRVAL_P(value) = buf; Z_STRLEN_P(value) = len; } diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 52179b1246..745eee09da 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1736,31 +1736,30 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a static int phar_analyze_path(const char *fname, const char *ext, int ext_len, int for_create TSRMLS_DC) /* {{{ */ { php_stream_statbuf ssb; - char *realpath, old, *a = (char *)(ext + ext_len); + char *realpath; + char *filename = estrndup(fname, (ext - fname) + ext_len); - old = *a; - *a = '\0'; - - if ((realpath = expand_filepath(fname, NULL TSRMLS_CC))) { + if ((realpath = expand_filepath(filename, NULL TSRMLS_CC))) { #ifdef PHP_WIN32 phar_unixify_path_separators(realpath, strlen(realpath)); #endif if (zend_hash_exists(&(PHAR_GLOBALS->phar_fname_map), realpath, strlen(realpath))) { - *a = old; efree(realpath); + efree(filename); return SUCCESS; } if (PHAR_G(manifest_cached) && zend_hash_exists(&cached_phars, realpath, strlen(realpath))) { - *a = old; efree(realpath); + efree(filename); return SUCCESS; } efree(realpath); } - if (SUCCESS == php_stream_stat_path((char *) fname, &ssb)) { - *a = old; + if (SUCCESS == php_stream_stat_path((char *) filename, &ssb)) { + + efree(filename); if (ssb.sb.st_mode & S_IFDIR) { return FAILURE; @@ -1775,57 +1774,56 @@ static int phar_analyze_path(const char *fname, const char *ext, int ext_len, in char *slash; if (!for_create) { - *a = old; + efree(filename); return FAILURE; } - slash = (char *) strrchr(fname, '/'); - *a = old; + slash = (char *) strrchr(filename, '/'); if (slash) { - old = *slash; *slash = '\0'; } - if (SUCCESS != php_stream_stat_path((char *) fname, &ssb)) { - if (slash) { - *slash = old; - } else { - if (!(realpath = expand_filepath(fname, NULL TSRMLS_CC))) { + if (SUCCESS != php_stream_stat_path((char *) filename, &ssb)) { + if (!slash) { + if (!(realpath = expand_filepath(filename, NULL TSRMLS_CC))) { + efree(filename); return FAILURE; } #ifdef PHP_WIN32 phar_unixify_path_separators(realpath, strlen(realpath)); #endif - a = strstr(realpath, fname) + ((ext - fname) + ext_len); - *a = '\0'; + slash = strstr(realpath, filename) + ((ext - fname) + ext_len); + *slash = '\0'; slash = strrchr(realpath, '/'); if (slash) { *slash = '\0'; } else { efree(realpath); + efree(filename); return FAILURE; } if (SUCCESS != php_stream_stat_path(realpath, &ssb)) { efree(realpath); + efree(filename); return FAILURE; } efree(realpath); if (ssb.sb.st_mode & S_IFDIR) { + efree(filename); return SUCCESS; } } + efree(filename); return FAILURE; } - if (slash) { - *slash = old; - } + efree(filename); if (ssb.sb.st_mode & S_IFDIR) { return SUCCESS; diff --git a/ext/standard/array.c b/ext/standard/array.c index 1988ea3a44..cd9b398355 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -1653,24 +1653,28 @@ PHP_FUNCTION(range) high = (unsigned char *)Z_STRVAL_P(zhigh); if (*low > *high) { /* Negative Steps */ + unsigned char ch = *low; + if (lstep <= 0) { err = 1; goto err; } - for (; *low >= *high; (*low) -= (unsigned int)lstep) { - add_next_index_stringl(return_value, (const char *)low, 1, 1); - if (((signed int)*low - lstep) < 0) { + for (; ch >= *high; ch -= (unsigned int)lstep) { + add_next_index_stringl(return_value, (const char *)&ch, 1, 1); + if (((signed int)ch - lstep) < 0) { break; } } } else if (*high > *low) { /* Positive Steps */ + unsigned char ch = *low; + if (lstep <= 0) { err = 1; goto err; } - for (; *low <= *high; (*low) += (unsigned int)lstep) { - add_next_index_stringl(return_value, (const char *)low, 1, 1); - if (((signed int)*low + lstep) > 255) { + for (; ch <= *high; ch += (unsigned int)lstep) { + add_next_index_stringl(return_value, (const char *)&ch, 1, 1); + if (((signed int)ch + lstep) > 255) { break; } } diff --git a/ext/standard/string.c b/ext/standard/string.c index 88b8099683..1ffbaa9663 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -3589,7 +3589,7 @@ static void php_str_replace_in_subject(zval *search, zval *replace, zval **subje replace_value, replace_len, &Z_STRLEN(temp_result), case_sensitivity, replace_count); } - efree(Z_STRVAL_P(result)); + str_efree(Z_STRVAL_P(result)); Z_STRVAL_P(result) = Z_STRVAL(temp_result); Z_STRLEN_P(result) = Z_STRLEN(temp_result); @@ -4244,6 +4244,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow, char *tbuf, *buf, *p, *tp, *rp, c, lc; int br, i=0, depth=0, in_q = 0; int state = 0, pos; + char *allow_free; if (stateptr) state = *stateptr; @@ -4255,7 +4256,12 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, int len, int *stateptr, char *allow, rp = rbuf; br = 0; if (allow) { - php_strtolower(allow, allow_len); + if (IS_INTERNED(allow)) { + allow_free = allow = zend_str_tolower_dup(allow, allow_len); + } else { + allow_free = NULL; + php_strtolower(allow, allow_len); + } tbuf = emalloc(PHP_TAG_BUF_SIZE + 1); tp = tbuf; } else { @@ -4494,8 +4500,12 @@ reg_char: *rp = '\0'; } efree(buf); - if (allow) + if (allow) { efree(tbuf); + if (allow_free) { + efree(allow_free); + } + } if (stateptr) *stateptr = state; diff --git a/win32/build/config.w32 b/win32/build/config.w32 index c52ce01737..d876566e14 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -325,7 +325,7 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \ zend_stream.c zend_iterators.c zend_interfaces.c zend_objects.c \ zend_object_handlers.c zend_objects_API.c \ zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c \ - zend_float.c"); + zend_float.c zend_string.c"); if (VCVERS == 1200) { AC_DEFINE('ZEND_DVAL_TO_LVAL_CAST_OK', 1); |