]> granicus.if.org Git - php/commitdiff
Avoid reallocation and double copying of variable names.
authorDmitry Stogov <dmitry@zend.com>
Tue, 12 Dec 2017 10:47:47 +0000 (13:47 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 12 Dec 2017 10:47:47 +0000 (13:47 +0300)
main/php_variables.c

index 74aa8c52caaaa7dbe58955ee6fffd027069afe14..0bbabcdfafd141c477a6cda15ed7d21ac4f76534 100644 (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);
 }
 
+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);
 }
 /* }}} */