summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorMichael Wallner <mike@php.net>2013-09-17 10:50:49 +0200
committerMichael Wallner <mike@php.net>2013-09-17 10:50:49 +0200
commit1c15d70cbd91e3f502694a31704e959cf734d8da (patch)
tree922fc946cf4c9a151e268a7adea06a6a4f86ce2a /main
parent52ff129607a7193cccbc6bdfbf1c1e8586e8d0d2 (diff)
parent2438490addfbfba51e12246a74588b2382caa08a (diff)
downloadphp-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')
-rw-r--r--main/SAPI.c77
-rw-r--r--main/SAPI.h7
-rw-r--r--main/main.c1
-rw-r--r--main/php_content_types.c23
-rw-r--r--main/php_globals.h1
-rw-r--r--main/php_streams.h2
-rw-r--r--main/php_variables.c128
7 files changed, 143 insertions, 96 deletions
diff --git a/main/SAPI.c b/main/SAPI.c
index dcb2da629a..ccfb1e507d 100644
--- a/main/SAPI.c
+++ b/main/SAPI.c
@@ -180,10 +180,10 @@ SAPI_API void sapi_handle_post(void *arg TSRMLS_DC)
{
if (SG(request_info).post_entry && SG(request_info).content_type_dup) {
SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg TSRMLS_CC);
- if (SG(request_info).post_data) {
- efree(SG(request_info).post_data);
- SG(request_info).post_data = NULL;
- }
+ /*if (SG(request_info).request_body) {
+ php_stream_close(SG(request_info).request_body);
+ SG(request_info).request_body = NULL;
+ }*/
efree(SG(request_info).content_type_dup);
SG(request_info).content_type_dup = NULL;
}
@@ -253,35 +253,40 @@ static void sapi_read_post_data(TSRMLS_D)
SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
{
int read_bytes;
- int allocated_bytes=SAPI_POST_BLOCK_SIZE+1;
if ((SG(post_max_size) > 0) && (SG(request_info).content_length > SG(post_max_size))) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "POST Content-Length of %ld bytes exceeds the limit of %ld bytes",
SG(request_info).content_length, SG(post_max_size));
return;
}
- SG(request_info).post_data = emalloc(allocated_bytes);
+ SG(request_info).request_body = php_stream_temp_create(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE);
- for (;;) {
- read_bytes = sapi_module.read_post(SG(request_info).post_data+SG(read_post_bytes), SAPI_POST_BLOCK_SIZE TSRMLS_CC);
- if (read_bytes<=0) {
- break;
- }
- SG(read_post_bytes) += read_bytes;
- if ((SG(post_max_size) > 0) && (SG(read_post_bytes) > SG(post_max_size))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Actual POST length does not match Content-Length, and exceeds %ld bytes", SG(post_max_size));
- break;
- }
- if (read_bytes < SAPI_POST_BLOCK_SIZE) {
- break;
- }
- if (SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE >= allocated_bytes) {
- allocated_bytes = SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE+1;
- SG(request_info).post_data = erealloc(SG(request_info).post_data, allocated_bytes);
+ if (sapi_module.read_post) {
+ for (;;) {
+ char buffer[SAPI_POST_BLOCK_SIZE];
+
+ read_bytes = sapi_module.read_post(buffer, SAPI_POST_BLOCK_SIZE TSRMLS_CC);
+ if (read_bytes<=0) {
+ /* failure */
+ break;
+ }
+ SG(read_post_bytes) += read_bytes;
+
+ if ((SG(post_max_size) > 0) && (SG(read_post_bytes) > SG(post_max_size))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Actual POST length does not match Content-Length, and exceeds %ld bytes", SG(post_max_size));
+ break;
+ }
+
+ php_stream_write(SG(request_info).request_body, buffer, read_bytes);
+
+ if (read_bytes < SAPI_POST_BLOCK_SIZE) {
+ /* done */
+ break;
+ }
}
+
+ php_stream_rewind(SG(request_info).request_body);
}
- SG(request_info).post_data[SG(read_post_bytes)] = 0; /* terminating NULL */
- SG(request_info).post_data_length = SG(read_post_bytes);
}
@@ -387,8 +392,7 @@ SAPI_API void sapi_activate_headers_only(TSRMLS_D)
SG(sapi_headers).http_status_line = NULL;
SG(sapi_headers).mimetype = NULL;
SG(read_post_bytes) = 0;
- SG(request_info).post_data = NULL;
- SG(request_info).raw_post_data = NULL;
+ SG(request_info).request_body = NULL;
SG(request_info).current_user = NULL;
SG(request_info).current_user_length = 0;
SG(request_info).no_headers = 0;
@@ -433,8 +437,7 @@ SAPI_API void sapi_activate(TSRMLS_D)
SG(callback_run) = 0;
SG(callback_func) = NULL;
SG(read_post_bytes) = 0;
- SG(request_info).post_data = NULL;
- SG(request_info).raw_post_data = NULL;
+ SG(request_info).request_body = NULL;
SG(request_info).current_user = NULL;
SG(request_info).current_user_length = 0;
SG(request_info).no_headers = 0;
@@ -452,14 +455,15 @@ SAPI_API void sapi_activate(TSRMLS_D)
/* Handle request method */
if (SG(server_context)) {
- if (PG(enable_post_data_reading) && SG(request_info).request_method) {
- if (SG(request_info).content_type && !strcmp(SG(request_info).request_method, "POST")) {
+ if (SG(request_info).request_method) {
+ if (PG(enable_post_data_reading)
+ && SG(request_info).content_type
+ && !strcmp(SG(request_info).request_method, "POST")) {
/* HTTP POST may contain form data to be processed into variables
* depending on given content type */
sapi_read_post_data(TSRMLS_C);
} else {
- /* Any other method with content payload will fill $HTTP_RAW_POST_DATA
- * if it is enabled by always_populate_raw_post_data.
+ /* Any other method with content payload will fill php://input stream.
* It's up to the webserver to decide whether to allow a method or not. */
SG(request_info).content_type_dup = NULL;
if (sapi_module.default_post_reader) {
@@ -494,9 +498,9 @@ static void sapi_send_headers_free(TSRMLS_D)
SAPI_API void sapi_deactivate(TSRMLS_D)
{
zend_llist_destroy(&SG(sapi_headers).headers);
- if (SG(request_info).post_data) {
- efree(SG(request_info).post_data);
- } else if (SG(server_context)) {
+ if (SG(request_info).request_body) {
+ SG(request_info).request_body = NULL;
+ } else if (SG(server_context)) {
if(sapi_module.read_post) {
/* make sure we've consumed all request input data */
char dummy[SAPI_POST_BLOCK_SIZE];
@@ -507,9 +511,6 @@ SAPI_API void sapi_deactivate(TSRMLS_D)
}
}
}
- if (SG(request_info).raw_post_data) {
- efree(SG(request_info).raw_post_data);
- }
if (SG(request_info).auth_user) {
efree(SG(request_info).auth_user);
}
diff --git a/main/SAPI.h b/main/SAPI.h
index 6fc60c8865..ed6b0494f4 100644
--- a/main/SAPI.h
+++ b/main/SAPI.h
@@ -32,8 +32,7 @@
#include <sys/stat.h>
#define SAPI_OPTION_NO_CHDIR 1
-
-#define SAPI_POST_BLOCK_SIZE 4000
+#define SAPI_POST_BLOCK_SIZE 0x4000
#ifdef PHP_WIN32
# ifdef SAPI_EXPORTS
@@ -80,14 +79,14 @@ END_EXTERN_C()
typedef struct {
const char *request_method;
char *query_string;
- char *post_data, *raw_post_data;
char *cookie_data;
long content_length;
- int64_t post_data_length, raw_post_data_length;
char *path_translated;
char *request_uri;
+ struct _php_stream *request_body;
+
const char *content_type;
zend_bool headers_only;
diff --git a/main/main.c b/main/main.c
index 2f56afa03a..1cc842b212 100644
--- a/main/main.c
+++ b/main/main.c
@@ -562,7 +562,6 @@ PHP_INI_BEGIN()
STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("enable_post_data_reading", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, enable_post_data_reading, php_core_globals, core_globals)
- STD_PHP_INI_BOOLEAN("always_populate_raw_post_data", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, always_populate_raw_post_data, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("realpath_cache_size", "16K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals)
diff --git a/main/php_content_types.c b/main/php_content_types.c
index c4433978ed..3346efc50e 100644
--- a/main/php_content_types.c
+++ b/main/php_content_types.c
@@ -37,34 +37,11 @@ static sapi_post_entry php_post_entries[] = {
*/
SAPI_API SAPI_POST_READER_FUNC(php_default_post_reader)
{
- char *data;
- int length;
-
- /* $HTTP_RAW_POST_DATA registration */
if (!strcmp(SG(request_info).request_method, "POST")) {
if (NULL == SG(request_info).post_entry) {
/* no post handler registered, so we just swallow the data */
sapi_read_standard_form_data(TSRMLS_C);
}
-
- /* For unknown content types we create HTTP_RAW_POST_DATA even if always_populate_raw_post_data off,
- * this is in-effecient, but we need to keep doing it for BC reasons (for now) */
- if ((PG(always_populate_raw_post_data) || NULL == SG(request_info).post_entry) && SG(request_info).post_data) {
- length = SG(request_info).post_data_length;
- data = estrndup(SG(request_info).post_data, length);
- SET_VAR_STRINGL("HTTP_RAW_POST_DATA", data, length);
- }
- }
-
- /* for php://input stream:
- some post handlers modify the content of request_info.post_data
- so for now we need a copy for the php://input stream
- in the long run post handlers should be changed to not touch
- request_info.post_data for memory preservation reasons
- */
- if (SG(request_info).post_data) {
- SG(request_info).raw_post_data = estrndup(SG(request_info).post_data, SG(request_info).post_data_length);
- SG(request_info).raw_post_data_length = SG(request_info).post_data_length;
}
}
/* }}} */
diff --git a/main/php_globals.h b/main/php_globals.h
index 256765d665..fa2fe3b232 100644
--- a/main/php_globals.h
+++ b/main/php_globals.h
@@ -131,7 +131,6 @@ struct _php_core_globals {
zend_bool during_request_startup;
zend_bool allow_url_fopen;
zend_bool enable_post_data_reading;
- zend_bool always_populate_raw_post_data;
zend_bool report_zend_debug;
int last_error_type;
diff --git a/main/php_streams.h b/main/php_streams.h
index c56014c62e..c9732b4848 100644
--- a/main/php_streams.h
+++ b/main/php_streams.h
@@ -242,7 +242,7 @@ PHPAPI php_stream *_php_stream_alloc(php_stream_ops *ops, void *abstract,
END_EXTERN_C()
#define php_stream_alloc(ops, thisptr, persistent_id, mode) _php_stream_alloc((ops), (thisptr), (persistent_id), (mode) STREAMS_CC TSRMLS_CC)
-#define php_stream_get_resource_id(stream) (stream)->rsrc_id
+#define php_stream_get_resource_id(stream) ((php_stream *)(stream))->rsrc_id
#if ZEND_DEBUG
/* use this to tell the stream that it is OK if we don't explicitly close it */
# define php_stream_auto_cleanup(stream) { (stream)->__exposed++; }
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);
+ }
}
}