From: Dmitry Stogov Date: Tue, 12 Dec 2017 10:47:47 +0000 (+0300) Subject: Avoid reallocation and double copying of variable names. X-Git-Tag: php-7.3.0alpha1~818 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fe4c7898d85b4958aa90daa6db332f7033f52694;p=php Avoid reallocation and double copying of variable names. --- diff --git a/main/php_variables.c b/main/php_variables.c index 74aa8c52ca..0bbabcdfaf 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -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); } +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) { char *p = NULL; @@ -236,12 +244,13 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars } } else { plain_var: - ZVAL_COPY_VALUE(&gpc_element, val); if (!index) { - if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) { - zval_ptr_dtor(&gpc_element); + if (zend_hash_next_index_insert(symtable1, val) == NULL) { + zval_ptr_dtor(val); } } else { + zend_ulong idx; + /* * 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 @@ -251,11 +260,11 @@ plain_var: if (Z_TYPE(PG(http_globals)[TRACK_VARS_COOKIE]) != IS_UNDEF && symtable1 == Z_ARRVAL(PG(http_globals)[TRACK_VARS_COOKIE]) && 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 { - zend_string *key = zend_string_init_interned(index, index_len, 0); - gpc_element_p = zend_symtable_update_ind(symtable1, key, &gpc_element); - zend_string_release(key); + php_register_variable_quick(index, index_len, val, symtable1); } } } @@ -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) { - char buf[128]; - char **env, *p, *t = buf; - size_t alloc_size = sizeof(buf); - unsigned long nlen; /* ptrdiff_t is not portable */ + char **env, *p; + size_t name_len, len; + zval val; + zend_ulong idx; for (env = environ; env != NULL && *env != NULL; env++) { p = strchr(*env, '='); - if (!p) { /* malformed entry? */ + if (!p + || p == *env + || !valid_environment_name(*env, p)) { + /* malformed entry? */ continue; } - nlen = p - *env; - if (nlen >= alloc_size) { - alloc_size = nlen + 64; - t = (t == buf ? emalloc(alloc_size): erealloc(t, alloc_size)); + name_len = p - *env; + p++; + len = strlen(p); + 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)); + } + if (ZEND_HANDLE_NUMERIC_STR(*env, name_len, idx)) { + zend_hash_index_update(Z_ARRVAL_P(array_ptr), idx, &val); + } else { + php_register_variable_quick(*env, name_len, &val, Z_ARRVAL_P(array_ptr)); } - memcpy(t, *env, nlen); - t[nlen] = '\0'; - php_register_variable(t, p + 1, 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) { - 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]); - array_init(&PG(http_globals)[TRACK_VARS_SERVER]); + zval_ptr_dtor(arr); + array_init(arr); /* 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 */ 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) { - 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) { - 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 */ - ZVAL_DOUBLE(&request_time_float, sapi_get_request_time()); - php_register_variable_ex("REQUEST_TIME_FLOAT", &request_time_float, &PG(http_globals)[TRACK_VARS_SERVER]); - ZVAL_LONG(&request_time_long, zend_dval_to_lval(Z_DVAL(request_time_float))); - php_register_variable_ex("REQUEST_TIME", &request_time_long, &PG(http_globals)[TRACK_VARS_SERVER]); + ZVAL_DOUBLE(&tmp, sapi_get_request_time()); + php_register_variable_quick("REQUEST_TIME_FLOAT", sizeof("REQUEST_TIME_FLOAT")-1, &tmp, ht); + ZVAL_LONG(&tmp, zend_dval_to_lval(Z_DVAL(tmp))); + php_register_variable_quick("REQUEST_TIME", sizeof("REQUEST_TIME")-1, &tmp, ht); } /* }}} */