]> granicus.if.org Git - php/commitdiff
Added concept of interned strings. All strings constants known at compile time are...
authorDmitry Stogov <dmitry@php.net>
Tue, 20 Apr 2010 11:05:54 +0000 (11:05 +0000)
committerDmitry Stogov <dmitry@php.net>
Tue, 20 Apr 2010 11:05:54 +0000 (11:05 +0000)
30 files changed:
NEWS
Zend/Makefile.am
Zend/Zend.dsp
Zend/ZendTS.dsp
Zend/zend.c
Zend/zend.h
Zend/zend_API.c
Zend/zend_builtin_functions.c
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_constants.c
Zend/zend_execute.c
Zend/zend_execute_API.c
Zend/zend_globals.h
Zend/zend_hash.c
Zend/zend_hash.h
Zend/zend_language_scanner.l
Zend/zend_opcode.c
Zend/zend_operators.c
Zend/zend_string.c [new file with mode: 0644]
Zend/zend_string.h [new file with mode: 0644]
Zend/zend_variables.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
configure.in
ext/filter/sanitizing_filters.c
ext/phar/phar.c
ext/standard/array.c
ext/standard/string.c
win32/build/config.w32

diff --git a/NEWS b/NEWS
index 72b8ffbf69bc43a9b082222d6fd39372826198ad..7c302b58b8874fd7c7bcb97bcd54d21138f3a22f 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -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)
index 219d2d3fc94f7031aa0259942c4afc9f143fb00f..04b51081bfb5b8cbd50a739098698390b478db4e 100644 (file)
@@ -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@
index 0a7ed7753440fc27f8880979e82618bb284cb263..2a05c131e4a57796c3be7b7fe39127ac810e7ad8 100644 (file)
@@ -243,6 +243,10 @@ SOURCE=.\zend_stream.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\zend_string.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\zend_strtod.c\r
 # End Source File\r
 # Begin Source File\r
@@ -411,6 +415,10 @@ SOURCE=.\zend_stream.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\zend_string.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\zend_strtod.h\r
 # End Source File\r
 # Begin Source File\r
index 2295b89ebb778a47a1282246f49b911a3cfb0fc4..c08cc77faafce211b3782cfa31fbe7a1d0d03aab 100644 (file)
@@ -273,6 +273,10 @@ SOURCE=.\zend_stream.c
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\zend_string.c\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\zend_strtod.c\r
 # End Source File\r
 # Begin Source File\r
@@ -445,6 +449,10 @@ SOURCE=.\zend_stream.h
 # End Source File\r
 # Begin Source File\r
 \r
+SOURCE=.\zend_string.h\r
+# End Source File\r
+# Begin Source File\r
+\r
 SOURCE=.\zend_strtod.h\r
 # End Source File\r
 # Begin Source File\r
index 53bae4c95fba06248bbb0860cb66ed7b6d2535ea..698992a6e6103b39f769b1e578f635664cb1c025 100644 (file)
@@ -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);
 }
 /* }}} */
 
index fce65e0337fc0d0271b1266b25caf639814513bf..6348e5997cdf5f482a75b5d519906c7629bc0b33 100644 (file)
@@ -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)
 
index c08e43d35da7d8b25360604c3558cf67d7f442db..a7b73ea0177c1fac0406fe1127c6e9e6f9f58c69 100644 (file)
@@ -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**)&reg_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);
 
index ce4a1be893873ae23c18e879f3513aa438c0f8e9..7506401df20bd3c79c63e3d8f3e8a9b608267814 100644 (file)
@@ -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) {
index 5a57f8e03f4d0ed1bc65e4a458630dba8b940d8b..339d92a9cb3b1f7b1bdc62e015d3c93115ea8f84 100644 (file)
@@ -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);
        }
index b7185c7fcc94ae0d0541cb7ca799267917f4694f..33e60aeb0601a708d7ff77d28c54aecc3553da81 100644 (file)
@@ -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);
 
index 0543903e840b501c00e8ef41f5346ca7721b2b0f..1743ffd2a89a6992b0c3f31321afcf9e2bfbfde6 100644 (file)
@@ -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;
index f941167ea9d35f8833fb1ce8ec65a745401af03c..7966ed144c38608bbb7656f02b5f103315e4725d 100644 (file)
@@ -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) {
index d0ce7f1bf49403e90d8a056e68ba3a4cf1bc3fb7..fd4fb928e466dadcf1f84b4fb79ee5e8513bbf0b 100644 (file)
@@ -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);
index 368e88ec39a6b6f3c767d8c84ceaf4adfc974fec..19be67d1de7448d97d465e79c860e4e077ad8a24 100644 (file)
@@ -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;
index 69b6bdc16922b6bb5fe7f4559e42aaf809ed84a6..530afa7d348eec24668a360e20f8e29df96771a1 100644 (file)
@@ -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);
                }
index b26e0dbd6afa7c6686e38a7719655eef3e8b00ae..39a75fd1d4e882acfac5288ce90cde72bd3b0451 100644 (file)
@@ -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 {
index a4faff38253d56385a94f23b5d896551e602136d..2857c873683bf0ec322ace570d5cc47e16736899 100644 (file)
@@ -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);
 
index 9fdbd70870a18b683e60546b597b47f82bc80518..9e9b2f57679fec01ef461ab6c118baf509bc00db 100644 (file)
@@ -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);
                        }
                }
index 8af1edee50f19b275b3a2bd27da79a94843f1fb3..abc7489dbf586e6d9d58af973a04c587ff39dbc8 100644 (file)
@@ -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 (file)
index 0000000..098ad62
--- /dev/null
@@ -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 (file)
index 0000000..158efce
--- /dev/null
@@ -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:
+ */
index dce98ba22c354ebdad286192b27cac71cc1c0b70..47f246276177f85f1b04b3cd8590e41e3bd4f257 100644 (file)
@@ -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: {
index 0fe828d3dd3d45817480453b3b9823c25f9370e7..735c9daaa855c101a319ab3e900df50fb6e4e816 100644 (file)
@@ -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;
 
index 26434e5c6c084f8653806aaba7bad8bd0553b8ee..3650dfac24f9293e6d62001eb2c93b0785e6fbb3 100644 (file)
@@ -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;
index 230d93fbc6b870a1cc6e9fc5848f639bf89b5667..d88cf118976614c947385a056bc8471ad1ca0d6f 100644 (file)
@@ -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)
index c44d7a8e55ffb25199eb5e05b8a35b337db30f66..d54ced2f4b8396cd78a9a264918a15453f85ef0b 100644 (file)
@@ -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;
 }
index 52179b124610411ea665a62424df40ffe4ef07c3..745eee09daabae5885ba6fd3a1a59225cda00959 100644 (file)
@@ -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;
index 1988ea3a4483ec7e0438934ad13e17533ce43996..cd9b398355cb4503733633457a39031f474ac44e 100644 (file)
@@ -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;
                                }
                        }
index 88b80996833f28e0ec011240aec1da6307e4e310..1ffbaa9663a2f15caad12a52d75e28d1558fecb2 100644 (file)
@@ -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;
 
index c52ce017374abbc9b84cd0de37661fc69961ef42..d876566e14ef034aae9feb0e9abbe845c6c59cdb 100644 (file)
@@ -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);