Avoid reallocation and double copying of variable names.

This commit is contained in:
Dmitry Stogov 2017-12-12 13:47:47 +03:00
parent 2bbcc04c20
commit fe4c7898d8

View file

@ -59,6 +59,14 @@ PHPAPI void php_register_variable_safe(char *var, char *strval, size_t str_len,
php_register_variable_ex(var, &new_entry, track_vars_array); php_register_variable_ex(var, &new_entry, track_vars_array);
} }
static zend_always_inline void php_register_variable_quick(const char *name, size_t name_len, zval *val, HashTable *ht)
{
zend_string *key = zend_string_init_interned(name, name_len, 0);
zend_hash_update_ind(ht, key, val);
zend_string_release(key);
}
PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array) PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array)
{ {
char *p = NULL; char *p = NULL;
@ -236,12 +244,13 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars
} }
} else { } else {
plain_var: plain_var:
ZVAL_COPY_VALUE(&gpc_element, val);
if (!index) { if (!index) {
if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) { if (zend_hash_next_index_insert(symtable1, val) == NULL) {
zval_ptr_dtor(&gpc_element); zval_ptr_dtor(val);
} }
} else { } else {
zend_ulong idx;
/* /*
* According to rfc2965, more specific paths are listed above the less specific ones. * According to rfc2965, more specific paths are listed above the less specific ones.
* If we encounter a duplicate cookie name, we should skip it, since it is not possible * If we encounter a duplicate cookie name, we should skip it, since it is not possible
@ -251,11 +260,11 @@ plain_var:
if (Z_TYPE(PG(http_globals)[TRACK_VARS_COOKIE]) != IS_UNDEF && if (Z_TYPE(PG(http_globals)[TRACK_VARS_COOKIE]) != IS_UNDEF &&
symtable1 == Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]) && symtable1 == Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]) &&
zend_symtable_str_exists(symtable1, index, index_len)) { zend_symtable_str_exists(symtable1, index, index_len)) {
zval_ptr_dtor(&gpc_element); zval_ptr_dtor(val);
} else if (ZEND_HANDLE_NUMERIC_STR(index, index_len, idx)) {
zend_hash_index_update(symtable1, idx, val);
} else { } else {
zend_string *key = zend_string_init_interned(index, index_len, 0); php_register_variable_quick(index, index_len, val, symtable1);
gpc_element_p = zend_symtable_update_ind(symtable1, key, &gpc_element);
zend_string_release(key);
} }
} }
} }
@ -520,29 +529,48 @@ next_cookie:
} }
} }
static zend_always_inline int valid_environment_name(const char *name, const char *end)
{
const char *s;
for (s = name; s < end; s++) {
if (*s == ' ' | *s == '.' || *s == '[') {
return 0;
}
}
return 1;
}
void _php_import_environment_variables(zval *array_ptr) void _php_import_environment_variables(zval *array_ptr)
{ {
char buf[128]; char **env, *p;
char **env, *p, *t = buf; size_t name_len, len;
size_t alloc_size = sizeof(buf); zval val;
unsigned long nlen; /* ptrdiff_t is not portable */ zend_ulong idx;
for (env = environ; env != NULL && *env != NULL; env++) { for (env = environ; env != NULL && *env != NULL; env++) {
p = strchr(*env, '='); p = strchr(*env, '=');
if (!p) { /* malformed entry? */ if (!p
|| p == *env
|| !valid_environment_name(*env, p)) {
/* malformed entry? */
continue; continue;
} }
nlen = p - *env; name_len = p - *env;
if (nlen >= alloc_size) { p++;
alloc_size = nlen + 64; len = strlen(p);
t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size)); if (len == 0) {
ZVAL_EMPTY_STRING(&val);
} else if (len == 1) {
ZVAL_INTERNED_STR(&val, ZSTR_CHAR((zend_uchar)*p));
} else {
ZVAL_NEW_STR(&val, zend_string_init(p, len, 0));
} }
memcpy(t, *env, nlen); if (ZEND_HANDLE_NUMERIC_STR(*env, name_len, idx)) {
t[nlen] = '\0'; zend_hash_index_update(Z_ARRVAL_P(array_ptr), idx, &val);
php_register_variable(t, p + 1, array_ptr); } else {
php_register_variable_quick(*env, name_len, &val, Z_ARRVAL_P(array_ptr));
} }
if (t != buf && t != NULL) {
efree(t);
} }
} }
@ -622,32 +650,38 @@ PHPAPI void php_build_argv(char *s, zval *track_vars_array)
*/ */
static inline void php_register_server_variables(void) static inline void php_register_server_variables(void)
{ {
zval request_time_float, request_time_long; zval tmp;
zval *arr = &PG(http_globals)[TRACK_VARS_SERVER];
HashTable *ht;
zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_SERVER]); zval_ptr_dtor(arr);
array_init(&PG(http_globals)[TRACK_VARS_SERVER]); array_init(arr);
/* Server variables */ /* Server variables */
if (sapi_module.register_server_variables) { if (sapi_module.register_server_variables) {
sapi_module.register_server_variables(&PG(http_globals)[TRACK_VARS_SERVER]); sapi_module.register_server_variables(arr);
} }
ht = Z_ARRVAL_P(arr);
/* PHP Authentication support */ /* PHP Authentication support */
if (SG(request_info).auth_user) { if (SG(request_info).auth_user) {
php_register_variable("PHP_AUTH_USER", SG(request_info).auth_user, &PG(http_globals)[TRACK_VARS_SERVER]); ZVAL_STRING(&tmp, SG(request_info).auth_user);
php_register_variable_quick("PHP_AUTH_USER", sizeof("PHP_AUTH_USER")-1, &tmp, ht);
} }
if (SG(request_info).auth_password) { if (SG(request_info).auth_password) {
php_register_variable("PHP_AUTH_PW", SG(request_info).auth_password, &PG(http_globals)[TRACK_VARS_SERVER]); ZVAL_STRING(&tmp, SG(request_info).auth_password);
php_register_variable_quick("PHP_AUTH_PW", sizeof("PHP_AUTH_PW")-1, &tmp, ht);
} }
if (SG(request_info).auth_digest) { if (SG(request_info).auth_digest) {
php_register_variable("PHP_AUTH_DIGEST", SG(request_info).auth_digest, &PG(http_globals)[TRACK_VARS_SERVER]); ZVAL_STRING(&tmp, SG(request_info).auth_digest);
php_register_variable_quick("PHP_AUTH_DIGEST", sizeof("PHP_AUTH_DIGEST")-1, &tmp, ht);
} }
/* store request init time */ /* store request init time */
ZVAL_DOUBLE(&request_time_float, sapi_get_request_time()); ZVAL_DOUBLE(&tmp, sapi_get_request_time());
php_register_variable_ex("REQUEST_TIME_FLOAT", &request_time_float, &PG(http_globals)[TRACK_VARS_SERVER]); php_register_variable_quick("REQUEST_TIME_FLOAT", sizeof("REQUEST_TIME_FLOAT")-1, &tmp, ht);
ZVAL_LONG(&request_time_long, zend_dval_to_lval(Z_DVAL(request_time_float))); ZVAL_LONG(&tmp, zend_dval_to_lval(Z_DVAL(tmp)));
php_register_variable_ex("REQUEST_TIME", &request_time_long, &PG(http_globals)[TRACK_VARS_SERVER]); php_register_variable_quick("REQUEST_TIME", sizeof("REQUEST_TIME")-1, &tmp, ht);
} }
/* }}} */ /* }}} */