--- embedaddon/php/Zend/zend_constants.c 2012/02/21 23:47:52 1.1.1.1 +++ embedaddon/php/Zend/zend_constants.c 2012/05/29 12:34:35 1.1.1.2 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_constants.c,v 1.1.1.1 2012/02/21 23:47:52 misho Exp $ */ +/* $Id: zend_constants.c,v 1.1.1.2 2012/05/29 12:34:35 misho Exp $ */ #include "zend.h" #include "zend_constants.h" @@ -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); } @@ -113,76 +115,6 @@ void zend_register_standard_constants(TSRMLS_D) REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS); -#if SUHOSIN_PATCH - REGISTER_MAIN_LONG_CONSTANT("S_MEMORY", S_MEMORY, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("S_VARS", S_VARS, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("S_FILES", S_FILES, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("S_INCLUDE", S_INCLUDE, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("S_SQL", S_SQL, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("S_EXECUTOR", S_EXECUTOR, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("S_MAIL", S_MAIL, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("S_SESSION", S_SESSION, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("S_MISC", S_MISC, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("S_INTERNAL", S_INTERNAL, CONST_PERSISTENT | CONST_CS); - REGISTER_MAIN_LONG_CONSTANT("S_ALL", S_ALL, CONST_PERSISTENT | CONST_CS); - - /* error levels */ - REGISTER_MAIN_LONG_CONSTANT("LOG_EMERG", LOG_EMERG, CONST_CS | CONST_PERSISTENT); /* system unusable */ - REGISTER_MAIN_LONG_CONSTANT("LOG_ALERT", LOG_ALERT, CONST_CS | CONST_PERSISTENT); /* immediate action required */ - REGISTER_MAIN_LONG_CONSTANT("LOG_CRIT", LOG_CRIT, CONST_CS | CONST_PERSISTENT); /* critical conditions */ - REGISTER_MAIN_LONG_CONSTANT("LOG_ERR", LOG_ERR, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_WARNING", LOG_WARNING, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_NOTICE", LOG_NOTICE, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_INFO", LOG_INFO, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_DEBUG", LOG_DEBUG, CONST_CS | CONST_PERSISTENT); - /* facility: type of program logging the message */ - REGISTER_MAIN_LONG_CONSTANT("LOG_KERN", LOG_KERN, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_USER", LOG_USER, CONST_CS | CONST_PERSISTENT); /* generic user level */ - REGISTER_MAIN_LONG_CONSTANT("LOG_MAIL", LOG_MAIL, CONST_CS | CONST_PERSISTENT); /* log to email */ - REGISTER_MAIN_LONG_CONSTANT("LOG_DAEMON", LOG_DAEMON, CONST_CS | CONST_PERSISTENT); /* other system daemons */ - REGISTER_MAIN_LONG_CONSTANT("LOG_AUTH", LOG_AUTH, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_SYSLOG", LOG_SYSLOG, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_LPR", LOG_LPR, CONST_CS | CONST_PERSISTENT); -#ifdef LOG_NEWS - /* No LOG_NEWS on HP-UX */ - REGISTER_MAIN_LONG_CONSTANT("LOG_NEWS", LOG_NEWS, CONST_CS | CONST_PERSISTENT); /* usenet new */ -#endif -#ifdef LOG_UUCP - /* No LOG_UUCP on HP-UX */ - REGISTER_MAIN_LONG_CONSTANT("LOG_UUCP", LOG_UUCP, CONST_CS | CONST_PERSISTENT); -#endif -#ifdef LOG_CRON - /* apparently some systems don't have this one */ - REGISTER_MAIN_LONG_CONSTANT("LOG_CRON", LOG_CRON, CONST_CS | CONST_PERSISTENT); -#endif -#ifdef LOG_AUTHPRIV - /* AIX doesn't have LOG_AUTHPRIV */ - REGISTER_MAIN_LONG_CONSTANT("LOG_AUTHPRIV", LOG_AUTHPRIV, CONST_CS | CONST_PERSISTENT); -#endif -#ifndef PHP_WIN32 - REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL0", LOG_LOCAL0, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL1", LOG_LOCAL1, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL2", LOG_LOCAL2, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL3", LOG_LOCAL3, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL4", LOG_LOCAL4, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL5", LOG_LOCAL5, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL6", LOG_LOCAL6, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_LOCAL7", LOG_LOCAL7, CONST_CS | CONST_PERSISTENT); -#endif - /* options */ - REGISTER_MAIN_LONG_CONSTANT("LOG_PID", LOG_PID, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_CONS", LOG_CONS, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_ODELAY", LOG_ODELAY, CONST_CS | CONST_PERSISTENT); - REGISTER_MAIN_LONG_CONSTANT("LOG_NDELAY", LOG_NDELAY, CONST_CS | CONST_PERSISTENT); -#ifdef LOG_NOWAIT - REGISTER_MAIN_LONG_CONSTANT("LOG_NOWAIT", LOG_NOWAIT, CONST_CS | CONST_PERSISTENT); -#endif -#ifdef LOG_PERROR - /* AIX doesn't have LOG_PERROR */ - REGISTER_MAIN_LONG_CONSTANT("LOG_PERROR", LOG_PERROR, CONST_CS | CONST_PERSISTENT); /*log to stderr*/ -#endif -#endif - REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT, CONST_PERSISTENT | CONST_CS); REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS, CONST_PERSISTENT | CONST_CS); /* true/false constants */ @@ -209,7 +141,7 @@ void zend_register_standard_constants(TSRMLS_D) c.value.type = IS_NULL; zend_register_constant(&c TSRMLS_CC); - c.flags = CONST_PERSISTENT; + c.flags = CONST_PERSISTENT | CONST_CS; c.name = zend_strndup(ZEND_STRL("ZEND_THREAD_SAFE")); c.name_len = sizeof("ZEND_THREAD_SAFE"); @@ -292,7 +224,65 @@ ZEND_API void zend_register_string_constant(const char zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number TSRMLS_CC); } +static int zend_get_special_constant(const char *name, uint name_len, zend_constant **c TSRMLS_DC) +{ + int ret; + static char haltoff[] = "__COMPILER_HALT_OFFSET__"; + if (!EG(in_execution)) { + return 0; + } else if (name_len == sizeof("__CLASS__")-1 && + !memcmp(name, "__CLASS__", sizeof("__CLASS__")-1)) { + zend_constant tmp; + + /* Returned constants may be cached, so they have to be stored */ + if (EG(scope) && EG(scope)->name) { + int const_name_len; + char *const_name; + ALLOCA_FLAG(use_heap) + + const_name_len = sizeof("\0__CLASS__") + EG(scope)->name_length; + const_name = do_alloca(const_name_len, use_heap); + memcpy(const_name, "\0__CLASS__", sizeof("\0__CLASS__")-1); + zend_str_tolower_copy(const_name + sizeof("\0__CLASS__")-1, EG(scope)->name, EG(scope)->name_length); + if (zend_hash_find(EG(zend_constants), const_name, const_name_len, (void**)c) == FAILURE) { + zend_hash_add(EG(zend_constants), const_name, const_name_len, (void*)&tmp, sizeof(zend_constant), (void**)c); + memset(*c, 0, sizeof(zend_constant)); + Z_STRVAL((**c).value) = estrndup(EG(scope)->name, EG(scope)->name_length); + Z_STRLEN((**c).value) = EG(scope)->name_length; + Z_TYPE((**c).value) = IS_STRING; + } + free_alloca(const_name, use_heap); + } else { + if (zend_hash_find(EG(zend_constants), "\0__CLASS__", sizeof("\0__CLASS__"), (void**)c) == FAILURE) { + zend_hash_add(EG(zend_constants), "\0__CLASS__", sizeof("\0__CLASS__"), (void*)&tmp, sizeof(zend_constant), (void**)c); + memset(*c, 0, sizeof(zend_constant)); + Z_STRVAL((**c).value) = estrndup("", 0); + Z_STRLEN((**c).value) = 0; + Z_TYPE((**c).value) = IS_STRING; + } + } + return 1; + } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 && + !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) { + const char *cfilename; + char *haltname; + int len, clen; + + cfilename = zend_get_executed_filename(TSRMLS_C); + clen = strlen(cfilename); + /* check for __COMPILER_HALT_OFFSET__ */ + zend_mangle_property_name(&haltname, &len, haltoff, + sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0); + ret = zend_hash_find(EG(zend_constants), haltname, len+1, (void **) c); + efree(haltname); + return (ret == SUCCESS); + } else { + return 0; + } +} + + ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC) { zend_constant *c; @@ -307,29 +297,7 @@ ZEND_API int zend_get_constant(const char *name, uint retval=0; } } else { - static char haltoff[] = "__COMPILER_HALT_OFFSET__"; - - if (!EG(in_execution)) { - retval = 0; - } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 && - !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) { - char *cfilename, *haltname; - int len, clen; - - cfilename = zend_get_executed_filename(TSRMLS_C); - clen = strlen(cfilename); - /* check for __COMPILER_HALT_OFFSET__ */ - zend_mangle_property_name(&haltname, &len, haltoff, - sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0); - if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) { - retval = 1; - } else { - retval=0; - } - pefree(haltname, 0); - } else { - retval=0; - } + retval = zend_get_special_constant(name, name_len, &c TSRMLS_CC); } efree(lookup_name); } @@ -348,7 +316,7 @@ ZEND_API int zend_get_constant_ex(const char *name, ui { zend_constant *c; int retval = 1; - char *colon; + const char *colon; zend_class_entry *ce = NULL; char *class_name; zval **ret_constant; @@ -364,7 +332,7 @@ ZEND_API int zend_get_constant_ex(const char *name, ui colon > name && (*(colon - 1) == ':')) { int class_name_len = colon - name - 1; int const_name_len = name_len - class_name_len - 2; - char *constant_name = colon + 1; + const char *constant_name = colon + 1; char *lcname; class_name = estrndup(name, class_name_len); @@ -427,7 +395,7 @@ ZEND_API int zend_get_constant_ex(const char *name, ui /* compound constant name */ int prefix_len = colon - name; int const_name_len = name_len - prefix_len - 1; - char *constant_name = colon + 1; + const char *constant_name = colon + 1; char *lcname; int found_const = 0; @@ -480,11 +448,44 @@ finish: return zend_get_constant(name, name_len, result TSRMLS_CC); } +zend_constant *zend_quick_get_constant(const zend_literal *key, ulong flags TSRMLS_DC) +{ + zend_constant *c; + + if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE) { + key++; + if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE || + (c->flags & CONST_CS) != 0) { + if ((flags & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) { + key++; + if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE) { + key++; + if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE || + (c->flags & CONST_CS) != 0) { + + key--; + if (!zend_get_special_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) { + return NULL; + } + } + } + } else { + key--; + if (!zend_get_special_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) { + return NULL; + } + } + } + } + return c; +} + ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC) { char *lowercase_name = NULL; char *name; int ret = SUCCESS; + ulong chash = 0; #if 0 printf("Registering constant for module %d\n", c->module_number); @@ -494,22 +495,30 @@ ZEND_API int zend_register_constant(zend_constant *c T /* 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 = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC); name = lowercase_name; + chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0; } 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 = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC); name = lowercase_name; + + chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0; } else { name = c->name; } } + if (chash == 0) { + chash = zend_hash_func(name, c->name_len); + } /* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */ if ((c->name_len == sizeof("__COMPILER_HALT_OFFSET__") && !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) - || zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) { + || zend_hash_quick_add(EG(zend_constants), name, c->name_len, chash, (void *) c, sizeof(zend_constant), NULL)==FAILURE) { /* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */ if (c->name[0] == '\0' && c->name_len > sizeof("\0__COMPILER_HALT_OFFSET__") @@ -517,13 +526,13 @@ ZEND_API int zend_register_constant(zend_constant *c T name++; } 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;