diff options
author | Michael Wallner <mike@php.net> | 2013-09-17 10:50:49 +0200 |
---|---|---|
committer | Michael Wallner <mike@php.net> | 2013-09-17 10:50:49 +0200 |
commit | 1c15d70cbd91e3f502694a31704e959cf734d8da (patch) | |
tree | 922fc946cf4c9a151e268a7adea06a6a4f86ce2a /main/php_variables.c | |
parent | 52ff129607a7193cccbc6bdfbf1c1e8586e8d0d2 (diff) | |
parent | 2438490addfbfba51e12246a74588b2382caa08a (diff) | |
download | php-git-1c15d70cbd91e3f502694a31704e959cf734d8da.tar.gz |
Merge branch 'slim-postdata'
* slim-postdata:
slim post data
add NEWS entry; add simple test
more precise condition
make this work in vc11 too
Use int64_t and atoll() after discussion with johannes
ws
Patch for https://bugs.php.net/bug.php?id=44522 to allow uploading files above 2G.
Diffstat (limited to 'main/php_variables.c')
-rw-r--r-- | main/php_variables.c | 128 |
1 files changed, 100 insertions, 28 deletions
diff --git a/main/php_variables.c b/main/php_variables.c index 7018eae57b..af3a6aae7b 100644 --- a/main/php_variables.c +++ b/main/php_variables.c @@ -23,6 +23,7 @@ #include "php.h" #include "ext/standard/php_standard.h" #include "ext/standard/credits.h" +#include "ext/standard/php_smart_str.h" #include "php_variables.h" #include "php_globals.h" #include "php_content_types.h" @@ -228,44 +229,115 @@ plain_var: free_alloca(var_orig, use_heap); } +typedef struct post_var_data { + smart_str str; + char *ptr; + char *end; + uint64_t cnt; +} post_var_data_t; + +static zend_bool add_post_var(zval *arr, post_var_data_t *var, zend_bool eof TSRMLS_DC) +{ + char *ksep, *vsep; + size_t klen, vlen; + /* FIXME: string-size_t */ + unsigned int new_vlen; + + if (var->ptr >= var->end) { + return 0; + } + + vsep = memchr(var->ptr, '&', var->end - var->ptr); + if (!vsep) { + if (!eof) { + return 0; + } else { + vsep = var->end; + } + } + + ksep = memchr(var->ptr, '=', vsep - var->ptr); + if (ksep) { + *ksep = '\0'; + /* "foo=bar&" or "foo=&" */ + klen = ksep - var->ptr; + vlen = vsep - ++ksep; + } else { + ksep = ""; + /* "foo&" */ + klen = vsep - var->ptr; + vlen = 0; + } + + + php_url_decode(var->ptr, klen); + if (vlen) { + vlen = php_url_decode(ksep, vlen); + } + + if (sapi_module.input_filter(PARSE_POST, var->ptr, &ksep, vlen, &new_vlen TSRMLS_CC)) { + php_register_variable_safe(var->ptr, ksep, new_vlen, arr TSRMLS_CC); + } + + var->ptr = vsep + (vsep != var->end); + return 1; +} + +static inline int add_post_vars(zval *arr, post_var_data_t *vars, zend_bool eof TSRMLS_DC) +{ + uint64_t max_vars = PG(max_input_vars); + + vars->ptr = vars->str.c; + vars->end = vars->str.c + vars->str.len; + while (add_post_var(arr, vars, eof TSRMLS_CC)) { + if (++vars->cnt > max_vars) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Input variables exceeded %" PRIu64 ". " + "To increase the limit change max_input_vars in php.ini.", + max_vars); + return FAILURE; + } + } + + if (!eof) { + memmove(vars->str.c, vars->ptr, vars->str.len = vars->end - vars->ptr); + } + return SUCCESS; +} + SAPI_API SAPI_POST_HANDLER_FUNC(php_std_post_handler) { - char *var, *val, *e, *s, *p; - zval *array_ptr = (zval *) arg; - long count = 0; + zval *arr = (zval *) arg; + php_stream *s = SG(request_info).request_body; + post_var_data_t post_data; - if (SG(request_info).post_data == NULL) { - return; - } + if (s && SUCCESS == php_stream_rewind(s)) { + memset(&post_data, 0, sizeof(post_data)); - s = SG(request_info).post_data; - e = s + SG(request_info).post_data_length; + while (!php_stream_eof(s)) { + char buf[BUFSIZ] = {0}; + size_t len = php_stream_read(s, buf, BUFSIZ); - while (s < e && (p = memchr(s, '&', (e - s)))) { -last_value: - if ((val = memchr(s, '=', (p - s)))) { /* have a value */ - unsigned int val_len, new_val_len; + if (len && len != (size_t) -1) { + smart_str_appendl(&post_data.str, buf, len); - if (++count > PG(max_input_vars)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Input variables exceeded %ld. To increase the limit change max_input_vars in php.ini.", PG(max_input_vars)); - return; + if (SUCCESS != add_post_vars(arr, &post_data, 0 TSRMLS_CC)) { + if (post_data.str.c) { + efree(post_data.str.c); + } + return; + } } - var = s; - php_url_decode(var, (val - s)); - val++; - val_len = php_url_decode(val, (p - val)); - val = estrndup(val, val_len); - if (sapi_module.input_filter(PARSE_POST, var, &val, val_len, &new_val_len TSRMLS_CC)) { - php_register_variable_safe(var, val, new_val_len, array_ptr TSRMLS_CC); + if (len != BUFSIZ){ + break; } - efree(val); } - s = p + 1; - } - if (s < e) { - p = e; - goto last_value; + + add_post_vars(arr, &post_data, 1 TSRMLS_CC); + if (post_data.str.c) { + efree(post_data.str.c); + } } } |