diff options
Diffstat (limited to 'main/php_variables.c')
| -rw-r--r-- | main/php_variables.c | 176 | 
1 files changed, 104 insertions, 72 deletions
| diff --git a/main/php_variables.c b/main/php_variables.c index 916fc1295b..5ac61a4fa0 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -13,12 +13,10 @@     | license@php.net so we can mail you a copy immediately.               |     +----------------------------------------------------------------------+     | Authors: Rasmus Lerdorf <rasmus@lerdorf.on.ca>                       | -   |          Zeev Suraski <zeev@zend.com>                                | +   |          Zeev Suraski <zeev@php.net>                                 |     +----------------------------------------------------------------------+   */ -/* $Id$ */ -  #include <stdio.h>  #include "php.h"  #include "ext/standard/php_standard.h" @@ -59,6 +57,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_ex(key, 0); +} +  PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars_array)  {  	char *p = NULL; @@ -79,7 +85,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars  	if (!symtable1) {  		/* Nothing to do */ -		zval_dtor(val); +		zval_ptr_dtor_nogc(val);  		return;  	} @@ -110,7 +116,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars  	var_len = p - var;  	if (var_len==0) { /* empty variable name, or variable name with a space in it */ -		zval_dtor(val); +		zval_ptr_dtor_nogc(val);  		free_alloca(var_orig, use_heap);  		return;  	} @@ -124,7 +130,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars  						&& ex->symbol_table == symtable1) {  					if (memcmp(var, "this", sizeof("this")-1) == 0) {  						zend_throw_error(NULL, "Cannot re-assign $this"); -						zval_dtor(val); +						zval_ptr_dtor_nogc(val);  						free_alloca(var_orig, use_heap);  						return;  					} @@ -139,7 +145,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars  	if (symtable1 == &EG(symbol_table) &&  		var_len == sizeof("GLOBALS")-1 &&  		!memcmp(var, "GLOBALS", sizeof("GLOBALS")-1)) { -		zval_dtor(val); +		zval_ptr_dtor_nogc(val);  		free_alloca(var_orig, use_heap);  		return;  	} @@ -162,7 +168,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars  					zend_symtable_str_del(ht, var, var_len);  				} -				zval_dtor(val); +				zval_ptr_dtor_nogc(val);  				/* do not output the error message to the screen,  				 this helps us to to avoid "information disclosure" */ @@ -200,8 +206,8 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars  			if (!index) {  				array_init(&gpc_element);  				if ((gpc_element_p = zend_hash_next_index_insert(symtable1, &gpc_element)) == NULL) { -					zval_ptr_dtor(&gpc_element); -					zval_dtor(val); +					zend_array_destroy(Z_ARR(gpc_element)); +					zval_ptr_dtor_nogc(val);  					free_alloca(var_orig, use_heap);  					return;  				} @@ -216,7 +222,7 @@ PHPAPI void php_register_variable_ex(char *var_name, zval *val, zval *track_vars  						gpc_element_p = Z_INDIRECT_P(gpc_element_p);  					}  					if (Z_TYPE_P(gpc_element_p) != IS_ARRAY) { -						zval_ptr_dtor(gpc_element_p); +						zval_ptr_dtor_nogc(gpc_element_p);  						array_init(gpc_element_p);  					} else {  						SEPARATE_ARRAY(gpc_element_p); @@ -238,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_nogc(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 @@ -253,9 +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_nogc(val); +			} else if (ZEND_HANDLE_NUMERIC_STR(index, index_len, idx)) { +				zend_hash_index_update(symtable1, idx, val);  			} else { -				gpc_element_p = zend_symtable_str_update_ind(symtable1, index, index_len, &gpc_element); +				php_register_variable_quick(index, index_len, val, symtable1);  			}  		}  	} @@ -409,15 +418,15 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data)  			array_init(&array);  			switch (arg) {  				case PARSE_POST: -					zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]); +					zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_POST]);  					ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_POST], &array);  					break;  				case PARSE_GET: -					zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]); +					zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_GET]);  					ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_GET], &array);  					break;  				case PARSE_COOKIE: -					zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]); +					zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_COOKIE]);  					ZVAL_COPY_VALUE(&PG(http_globals)[TRACK_VARS_COOKIE], &array);  					break;  			} @@ -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);  	}  } @@ -572,7 +600,7 @@ PHPAPI void php_build_argv(char *s, zval *track_vars_array)  		for (i = 0; i < SG(request_info).argc; i++) {  			ZVAL_STRING(&tmp, SG(request_info).argv[i]);  			if (zend_hash_next_index_insert(Z_ARRVAL(arr), &tmp) == NULL) { -				zend_string_free(Z_STR(tmp)); +				zend_string_efree(Z_STR(tmp));  			}  		}  	} else 	if (s && *s) { @@ -586,7 +614,7 @@ PHPAPI void php_build_argv(char *s, zval *track_vars_array)  			ZVAL_STRING(&tmp, ss);  			count++;  			if (zend_hash_next_index_insert(Z_ARRVAL(arr), &tmp) == NULL) { -				zend_string_free(Z_STR(tmp)); +				zend_string_efree(Z_STR(tmp));  			}  			if (space) {  				*space = '+'; @@ -606,13 +634,13 @@ PHPAPI void php_build_argv(char *s, zval *track_vars_array)  	if (SG(request_info).argc) {  		Z_ADDREF(arr); -		zend_hash_str_update(&EG(symbol_table), "argv", sizeof("argv")-1, &arr); -		zend_hash_str_add(&EG(symbol_table), "argc", sizeof("argc")-1, &argc); +		zend_hash_update(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), &arr); +		zend_hash_update(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGC), &argc);  	}  	if (track_vars_array && Z_TYPE_P(track_vars_array) == IS_ARRAY) {  		Z_ADDREF(arr); -		zend_hash_str_update(Z_ARRVAL_P(track_vars_array), "argv", sizeof("argv")-1, &arr); -		zend_hash_str_update(Z_ARRVAL_P(track_vars_array), "argc", sizeof("argc")-1, &argc); +		zend_hash_update(Z_ARRVAL_P(track_vars_array), ZSTR_KNOWN(ZEND_STR_ARGV), &arr); +		zend_hash_update(Z_ARRVAL_P(track_vars_array), ZSTR_KNOWN(ZEND_STR_ARGC), &argc);  	}  	zval_ptr_dtor_nogc(&arr);  } @@ -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_nogc(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);  }  /* }}} */ @@ -665,15 +699,13 @@ static void php_autoglobal_merge(HashTable *dest, HashTable *src)  			|| (string_key && (dest_entry = zend_hash_find(dest, string_key)) == NULL)  			|| (string_key == NULL && (dest_entry = zend_hash_index_find(dest, num_key)) == NULL)  			|| Z_TYPE_P(dest_entry) != IS_ARRAY) { -			if (Z_REFCOUNTED_P(src_entry)) { -				Z_ADDREF_P(src_entry); -			} +			Z_TRY_ADDREF_P(src_entry);  			if (string_key) {  				if (!globals_check || ZSTR_LEN(string_key) != sizeof("GLOBALS") - 1  						|| memcmp(ZSTR_VAL(string_key), "GLOBALS", sizeof("GLOBALS") - 1)) {  					zend_hash_update(dest, string_key, src_entry); -				} else if (Z_REFCOUNTED_P(src_entry)) { -					Z_DELREF_P(src_entry); +				} else { +					Z_TRY_DELREF_P(src_entry);  				}  			} else {  				zend_hash_index_update(dest, num_key, src_entry); @@ -704,7 +736,7 @@ static zend_bool php_auto_globals_create_get(zend_string *name)  	if (PG(variables_order) && (strchr(PG(variables_order),'G') || strchr(PG(variables_order),'g'))) {  		sapi_module.treat_data(PARSE_GET, NULL, NULL);  	} else { -		zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_GET]); +		zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_GET]);  		array_init(&PG(http_globals)[TRACK_VARS_GET]);  	} @@ -723,7 +755,7 @@ static zend_bool php_auto_globals_create_post(zend_string *name)  		!strcasecmp(SG(request_info).request_method, "POST")) {  		sapi_module.treat_data(PARSE_POST, NULL, NULL);  	} else { -		zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_POST]); +		zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_POST]);  		array_init(&PG(http_globals)[TRACK_VARS_POST]);  	} @@ -738,7 +770,7 @@ static zend_bool php_auto_globals_create_cookie(zend_string *name)  	if (PG(variables_order) && (strchr(PG(variables_order),'C') || strchr(PG(variables_order),'c'))) {  		sapi_module.treat_data(PARSE_COOKIE, NULL, NULL);  	} else { -		zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_COOKIE]); +		zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_COOKIE]);  		array_init(&PG(http_globals)[TRACK_VARS_COOKIE]);  	} @@ -785,11 +817,11 @@ static zend_bool php_auto_globals_create_server(zend_string *name)  			if (SG(request_info).argc) {  				zval *argc, *argv; -				if ((argc = zend_hash_str_find_ind(&EG(symbol_table), "argc", sizeof("argc")-1)) != NULL && -					(argv = zend_hash_str_find_ind(&EG(symbol_table), "argv", sizeof("argv")-1)) != NULL) { +				if ((argc = zend_hash_find_ex_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGC), 1)) != NULL && +					(argv = zend_hash_find_ex_ind(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), 1)) != NULL) {  					Z_ADDREF_P(argv); -					zend_hash_str_update(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "argv", sizeof("argv")-1, argv); -					zend_hash_str_update(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), "argc", sizeof("argc")-1, argc); +					zend_hash_update(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), ZSTR_KNOWN(ZEND_STR_ARGV), argv); +					zend_hash_update(Z_ARRVAL(PG(http_globals)[TRACK_VARS_SERVER]), ZSTR_KNOWN(ZEND_STR_ARGC), argc);  				}  			} else {  				php_build_argv(SG(request_info).query_string, &PG(http_globals)[TRACK_VARS_SERVER]); @@ -797,7 +829,7 @@ static zend_bool php_auto_globals_create_server(zend_string *name)  		}  	} else { -		zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_SERVER]); +		zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_SERVER]);  		array_init(&PG(http_globals)[TRACK_VARS_SERVER]);  	} @@ -815,7 +847,7 @@ static zend_bool php_auto_globals_create_server(zend_string *name)  static zend_bool php_auto_globals_create_env(zend_string *name)  { -	zval_ptr_dtor(&PG(http_globals)[TRACK_VARS_ENV]); +	zval_ptr_dtor_nogc(&PG(http_globals)[TRACK_VARS_ENV]);  	array_init(&PG(http_globals)[TRACK_VARS_ENV]);  	if (PG(variables_order) && (strchr(PG(variables_order),'E') || strchr(PG(variables_order),'e'))) { @@ -875,13 +907,13 @@ static zend_bool php_auto_globals_create_request(zend_string *name)  void php_startup_auto_globals(void)  { -	zend_register_auto_global(zend_string_init("_GET", sizeof("_GET")-1, 1), 0, php_auto_globals_create_get); -	zend_register_auto_global(zend_string_init("_POST", sizeof("_POST")-1, 1), 0, php_auto_globals_create_post); -	zend_register_auto_global(zend_string_init("_COOKIE", sizeof("_COOKIE")-1, 1), 0, php_auto_globals_create_cookie); -	zend_register_auto_global(zend_string_init("_SERVER", sizeof("_SERVER")-1, 1), PG(auto_globals_jit), php_auto_globals_create_server); -	zend_register_auto_global(zend_string_init("_ENV", sizeof("_ENV")-1, 1), PG(auto_globals_jit), php_auto_globals_create_env); -	zend_register_auto_global(zend_string_init("_REQUEST", sizeof("_REQUEST")-1, 1), PG(auto_globals_jit), php_auto_globals_create_request); -	zend_register_auto_global(zend_string_init("_FILES", sizeof("_FILES")-1, 1), 0, php_auto_globals_create_files); +	zend_register_auto_global(zend_string_init_interned("_GET", sizeof("_GET")-1, 1), 0, php_auto_globals_create_get); +	zend_register_auto_global(zend_string_init_interned("_POST", sizeof("_POST")-1, 1), 0, php_auto_globals_create_post); +	zend_register_auto_global(zend_string_init_interned("_COOKIE", sizeof("_COOKIE")-1, 1), 0, php_auto_globals_create_cookie); +	zend_register_auto_global(zend_string_init_interned("_SERVER", sizeof("_SERVER")-1, 1), PG(auto_globals_jit), php_auto_globals_create_server); +	zend_register_auto_global(zend_string_init_interned("_ENV", sizeof("_ENV")-1, 1), PG(auto_globals_jit), php_auto_globals_create_env); +	zend_register_auto_global(zend_string_init_interned("_REQUEST", sizeof("_REQUEST")-1, 1), PG(auto_globals_jit), php_auto_globals_create_request); +	zend_register_auto_global(zend_string_init_interned("_FILES", sizeof("_FILES")-1, 1), 0, php_auto_globals_create_files);  }  /* | 
