Skip to content

Commit 1c15d70

Browse files
committed
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.
2 parents 52ff129 + 2438490 commit 1c15d70

File tree

13 files changed

+205
-207
lines changed

13 files changed

+205
-207
lines changed

ext/mbstring/mb_gpc.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ SAPI_POST_HANDLER_FUNC(php_mb_post_handler)
364364
{
365365
const mbfl_encoding *detected;
366366
php_mb_encoding_handler_info_t info;
367+
char *post_data_str = NULL;
367368

368369
MBSTRG(http_input_identify_post) = NULL;
369370

@@ -376,7 +377,10 @@ SAPI_POST_HANDLER_FUNC(php_mb_post_handler)
376377
info.num_from_encodings = MBSTRG(http_input_list_size);
377378
info.from_language = MBSTRG(language);
378379

379-
detected = _php_mb_encoding_handler_ex(&info, arg, SG(request_info).post_data TSRMLS_CC);
380+
php_stream_rewind(SG(request_info).request_body);
381+
php_stream_copy_to_mem(SG(request_info).request_body, &post_data_str, PHP_STREAM_COPY_ALL, 0);
382+
detected = _php_mb_encoding_handler_ex(&info, arg, post_data_str TSRMLS_CC);
383+
STR_FREE(post_data_str);
380384

381385
MBSTRG(http_input_identify) = detected;
382386
if (detected) {

ext/soap/soap.c

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,48 +1560,45 @@ PHP_METHOD(SoapServer, handle)
15601560
}
15611561

15621562
if (ZEND_NUM_ARGS() == 0) {
1563-
if (SG(request_info).raw_post_data) {
1564-
char *post_data = SG(request_info).raw_post_data;
1565-
int post_data_length = SG(request_info).raw_post_data_length;
1563+
if (SG(request_info).request_body && 0 == php_stream_rewind(SG(request_info).request_body)) {
15661564
zval **server_vars, **encoding;
1565+
php_stream_filter *zf = NULL;
15671566

15681567
zend_is_auto_global("_SERVER", sizeof("_SERVER")-1 TSRMLS_CC);
15691568
if (zend_hash_find(&EG(symbol_table), "_SERVER", sizeof("_SERVER"), (void **) &server_vars) == SUCCESS &&
15701569
Z_TYPE_PP(server_vars) == IS_ARRAY &&
15711570
zend_hash_find(Z_ARRVAL_PP(server_vars), "HTTP_CONTENT_ENCODING", sizeof("HTTP_CONTENT_ENCODING"), (void **) &encoding)==SUCCESS &&
15721571
Z_TYPE_PP(encoding) == IS_STRING) {
1573-
zval func;
1574-
zval retval;
1575-
zval param;
1576-
zval *params[1];
1577-
1578-
if ((strcmp(Z_STRVAL_PP(encoding),"gzip") == 0 ||
1579-
strcmp(Z_STRVAL_PP(encoding),"x-gzip") == 0) &&
1580-
zend_hash_exists(EG(function_table), "gzinflate", sizeof("gzinflate"))) {
1581-
ZVAL_STRING(&func, "gzinflate", 0);
1582-
params[0] = &param;
1583-
ZVAL_STRINGL(params[0], post_data+10, post_data_length-10, 0);
1584-
INIT_PZVAL(params[0]);
1585-
} else if (strcmp(Z_STRVAL_PP(encoding),"deflate") == 0 &&
1586-
zend_hash_exists(EG(function_table), "gzuncompress", sizeof("gzuncompress"))) {
1587-
ZVAL_STRING(&func, "gzuncompress", 0);
1588-
params[0] = &param;
1589-
ZVAL_STRINGL(params[0], post_data, post_data_length, 0);
1590-
INIT_PZVAL(params[0]);
1572+
1573+
if (strcmp(Z_STRVAL_PP(encoding),"gzip") == 0
1574+
|| strcmp(Z_STRVAL_PP(encoding),"x-gzip") == 0
1575+
|| strcmp(Z_STRVAL_PP(encoding),"deflate") == 0
1576+
) {
1577+
zval filter_params;
1578+
1579+
INIT_PZVAL(&filter_params);
1580+
array_init_size(&filter_params, 1);
1581+
add_assoc_long_ex(&filter_params, ZEND_STRS("window"), 0x2f); /* ANY WBITS */
1582+
1583+
zf = php_stream_filter_create("zlib.inflate", &filter_params, 0);
1584+
zval_dtor(&filter_params);
1585+
1586+
if (zf) {
1587+
php_stream_filter_append(&SG(request_info).request_body->readfilters, zf);
1588+
} else {
1589+
php_error_docref(NULL TSRMLS_CC, E_WARNING,"Can't uncompress compressed request");
1590+
return;
1591+
}
15911592
} else {
15921593
php_error_docref(NULL TSRMLS_CC, E_WARNING,"Request is compressed with unknown compression '%s'",Z_STRVAL_PP(encoding));
15931594
return;
15941595
}
1595-
if (call_user_function(CG(function_table), (zval**)NULL, &func, &retval, 1, params TSRMLS_CC) == SUCCESS &&
1596-
Z_TYPE(retval) == IS_STRING) {
1597-
doc_request = soap_xmlParseMemory(Z_STRVAL(retval),Z_STRLEN(retval));
1598-
zval_dtor(&retval);
1599-
} else {
1600-
php_error_docref(NULL TSRMLS_CC, E_WARNING,"Can't uncompress compressed request");
1601-
return;
1602-
}
1603-
} else {
1604-
doc_request = soap_xmlParseMemory(post_data, post_data_length);
1596+
}
1597+
1598+
doc_request = soap_xmlParseFile("php://input");
1599+
1600+
if (zf) {
1601+
php_stream_filter_remove(zf, 1);
16051602
}
16061603
} else {
16071604
zval_ptr_dtor(&retval);

ext/standard/php_fopen_wrapper.c

Lines changed: 28 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -71,43 +71,20 @@ static size_t php_stream_input_write(php_stream *stream, const char *buf, size_t
7171

7272
static size_t php_stream_input_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */
7373
{
74-
off_t *position = (off_t*)stream->abstract;
75-
size_t read_bytes = 0;
76-
77-
if (!stream->eof) {
78-
if (SG(request_info).raw_post_data) { /* data has already been read by a post handler */
79-
read_bytes = SG(request_info).raw_post_data_length - *position;
80-
if (read_bytes <= count) {
81-
stream->eof = 1;
82-
} else {
83-
read_bytes = count;
84-
}
85-
if (read_bytes) {
86-
memcpy(buf, SG(request_info).raw_post_data + *position, read_bytes);
87-
}
88-
} else if (sapi_module.read_post) {
89-
read_bytes = sapi_module.read_post(buf, count TSRMLS_CC);
90-
if (read_bytes <= 0) {
91-
stream->eof = 1;
92-
read_bytes = 0;
93-
}
94-
/* Increment SG(read_post_bytes) only when something was actually read. */
95-
SG(read_post_bytes) += read_bytes;
96-
} else {
97-
stream->eof = 1;
98-
}
99-
}
74+
php_stream *inner = stream->abstract;
10075

101-
*position += read_bytes;
76+
if (inner && inner->ops->read) {
77+
size_t read = inner->ops->read(inner, buf, count TSRMLS_CC);
78+
stream->eof = inner->eof;
79+
return read;
80+
}
10281

103-
return read_bytes;
82+
return -1;
10483
}
10584
/* }}} */
10685

10786
static int php_stream_input_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{{ */
10887
{
109-
efree(stream->abstract);
110-
11188
return 0;
11289
}
11390
/* }}} */
@@ -118,13 +95,25 @@ static int php_stream_input_flush(php_stream *stream TSRMLS_DC) /* {{{ */
11895
}
11996
/* }}} */
12097

98+
static int php_stream_input_seek(php_stream *stream, off_t offset, int whence, off_t *newoffset TSRMLS_DC) /* {{{ */
99+
{
100+
php_stream *inner = stream->abstract;
101+
102+
if (inner && inner->ops->seek) {
103+
return inner->ops->seek(inner, offset, whence, newoffset TSRMLS_CC);
104+
}
105+
106+
return -1;
107+
}
108+
/* }}} */
109+
121110
php_stream_ops php_stream_input_ops = {
122111
php_stream_input_write,
123112
php_stream_input_read,
124113
php_stream_input_close,
125114
php_stream_input_flush,
126115
"Input",
127-
NULL, /* seek */
116+
php_stream_input_seek,
128117
NULL, /* cast */
129118
NULL, /* stat */
130119
NULL /* set_option */
@@ -210,7 +199,12 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa
210199
}
211200
return NULL;
212201
}
213-
return php_stream_alloc(&php_stream_input_ops, ecalloc(1, sizeof(off_t)), 0, "rb");
202+
if (SG(request_info).request_body) {
203+
php_stream_rewind(SG(request_info).request_body);
204+
} else {
205+
sapi_read_standard_form_data(TSRMLS_C);
206+
}
207+
return php_stream_alloc(&php_stream_input_ops, SG(request_info).request_body, 0, "rb");
214208
}
215209

216210
if (!strcasecmp(path, "stdin")) {
@@ -259,8 +253,8 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa
259253
fd = dup(STDERR_FILENO);
260254
}
261255
} else if (!strncasecmp(path, "fd/", 3)) {
262-
char *start,
263-
*end;
256+
const char *start;
257+
char *end;
264258
long fildes_ori;
265259
int dtablesize;
266260

main/SAPI.c

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,10 @@ SAPI_API void sapi_handle_post(void *arg TSRMLS_DC)
180180
{
181181
if (SG(request_info).post_entry && SG(request_info).content_type_dup) {
182182
SG(request_info).post_entry->post_handler(SG(request_info).content_type_dup, arg TSRMLS_CC);
183-
if (SG(request_info).post_data) {
184-
efree(SG(request_info).post_data);
185-
SG(request_info).post_data = NULL;
186-
}
183+
/*if (SG(request_info).request_body) {
184+
php_stream_close(SG(request_info).request_body);
185+
SG(request_info).request_body = NULL;
186+
}*/
187187
efree(SG(request_info).content_type_dup);
188188
SG(request_info).content_type_dup = NULL;
189189
}
@@ -253,35 +253,40 @@ static void sapi_read_post_data(TSRMLS_D)
253253
SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
254254
{
255255
int read_bytes;
256-
int allocated_bytes=SAPI_POST_BLOCK_SIZE+1;
257256

258257
if ((SG(post_max_size) > 0) && (SG(request_info).content_length > SG(post_max_size))) {
259258
php_error_docref(NULL TSRMLS_CC, E_WARNING, "POST Content-Length of %ld bytes exceeds the limit of %ld bytes",
260259
SG(request_info).content_length, SG(post_max_size));
261260
return;
262261
}
263-
SG(request_info).post_data = emalloc(allocated_bytes);
262+
SG(request_info).request_body = php_stream_temp_create(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE);
264263

265-
for (;;) {
266-
read_bytes = sapi_module.read_post(SG(request_info).post_data+SG(read_post_bytes), SAPI_POST_BLOCK_SIZE TSRMLS_CC);
267-
if (read_bytes<=0) {
268-
break;
269-
}
270-
SG(read_post_bytes) += read_bytes;
271-
if ((SG(post_max_size) > 0) && (SG(read_post_bytes) > SG(post_max_size))) {
272-
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Actual POST length does not match Content-Length, and exceeds %ld bytes", SG(post_max_size));
273-
break;
274-
}
275-
if (read_bytes < SAPI_POST_BLOCK_SIZE) {
276-
break;
277-
}
278-
if (SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE >= allocated_bytes) {
279-
allocated_bytes = SG(read_post_bytes)+SAPI_POST_BLOCK_SIZE+1;
280-
SG(request_info).post_data = erealloc(SG(request_info).post_data, allocated_bytes);
264+
if (sapi_module.read_post) {
265+
for (;;) {
266+
char buffer[SAPI_POST_BLOCK_SIZE];
267+
268+
read_bytes = sapi_module.read_post(buffer, SAPI_POST_BLOCK_SIZE TSRMLS_CC);
269+
if (read_bytes<=0) {
270+
/* failure */
271+
break;
272+
}
273+
SG(read_post_bytes) += read_bytes;
274+
275+
if ((SG(post_max_size) > 0) && (SG(read_post_bytes) > SG(post_max_size))) {
276+
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Actual POST length does not match Content-Length, and exceeds %ld bytes", SG(post_max_size));
277+
break;
278+
}
279+
280+
php_stream_write(SG(request_info).request_body, buffer, read_bytes);
281+
282+
if (read_bytes < SAPI_POST_BLOCK_SIZE) {
283+
/* done */
284+
break;
285+
}
281286
}
287+
288+
php_stream_rewind(SG(request_info).request_body);
282289
}
283-
SG(request_info).post_data[SG(read_post_bytes)] = 0; /* terminating NULL */
284-
SG(request_info).post_data_length = SG(read_post_bytes);
285290
}
286291

287292

@@ -387,8 +392,7 @@ SAPI_API void sapi_activate_headers_only(TSRMLS_D)
387392
SG(sapi_headers).http_status_line = NULL;
388393
SG(sapi_headers).mimetype = NULL;
389394
SG(read_post_bytes) = 0;
390-
SG(request_info).post_data = NULL;
391-
SG(request_info).raw_post_data = NULL;
395+
SG(request_info).request_body = NULL;
392396
SG(request_info).current_user = NULL;
393397
SG(request_info).current_user_length = 0;
394398
SG(request_info).no_headers = 0;
@@ -433,8 +437,7 @@ SAPI_API void sapi_activate(TSRMLS_D)
433437
SG(callback_run) = 0;
434438
SG(callback_func) = NULL;
435439
SG(read_post_bytes) = 0;
436-
SG(request_info).post_data = NULL;
437-
SG(request_info).raw_post_data = NULL;
440+
SG(request_info).request_body = NULL;
438441
SG(request_info).current_user = NULL;
439442
SG(request_info).current_user_length = 0;
440443
SG(request_info).no_headers = 0;
@@ -452,14 +455,15 @@ SAPI_API void sapi_activate(TSRMLS_D)
452455

453456
/* Handle request method */
454457
if (SG(server_context)) {
455-
if (PG(enable_post_data_reading) && SG(request_info).request_method) {
456-
if (SG(request_info).content_type && !strcmp(SG(request_info).request_method, "POST")) {
458+
if (SG(request_info).request_method) {
459+
if (PG(enable_post_data_reading)
460+
&& SG(request_info).content_type
461+
&& !strcmp(SG(request_info).request_method, "POST")) {
457462
/* HTTP POST may contain form data to be processed into variables
458463
* depending on given content type */
459464
sapi_read_post_data(TSRMLS_C);
460465
} else {
461-
/* Any other method with content payload will fill $HTTP_RAW_POST_DATA
462-
* if it is enabled by always_populate_raw_post_data.
466+
/* Any other method with content payload will fill php://input stream.
463467
* It's up to the webserver to decide whether to allow a method or not. */
464468
SG(request_info).content_type_dup = NULL;
465469
if (sapi_module.default_post_reader) {
@@ -494,9 +498,9 @@ static void sapi_send_headers_free(TSRMLS_D)
494498
SAPI_API void sapi_deactivate(TSRMLS_D)
495499
{
496500
zend_llist_destroy(&SG(sapi_headers).headers);
497-
if (SG(request_info).post_data) {
498-
efree(SG(request_info).post_data);
499-
} else if (SG(server_context)) {
501+
if (SG(request_info).request_body) {
502+
SG(request_info).request_body = NULL;
503+
} else if (SG(server_context)) {
500504
if(sapi_module.read_post) {
501505
/* make sure we've consumed all request input data */
502506
char dummy[SAPI_POST_BLOCK_SIZE];
@@ -507,9 +511,6 @@ SAPI_API void sapi_deactivate(TSRMLS_D)
507511
}
508512
}
509513
}
510-
if (SG(request_info).raw_post_data) {
511-
efree(SG(request_info).raw_post_data);
512-
}
513514
if (SG(request_info).auth_user) {
514515
efree(SG(request_info).auth_user);
515516
}

main/SAPI.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@
3232
#include <sys/stat.h>
3333

3434
#define SAPI_OPTION_NO_CHDIR 1
35-
36-
#define SAPI_POST_BLOCK_SIZE 4000
35+
#define SAPI_POST_BLOCK_SIZE 0x4000
3736

3837
#ifdef PHP_WIN32
3938
# ifdef SAPI_EXPORTS
@@ -80,14 +79,14 @@ END_EXTERN_C()
8079
typedef struct {
8180
const char *request_method;
8281
char *query_string;
83-
char *post_data, *raw_post_data;
8482
char *cookie_data;
8583
long content_length;
86-
int64_t post_data_length, raw_post_data_length;
8784

8885
char *path_translated;
8986
char *request_uri;
9087

88+
struct _php_stream *request_body;
89+
9190
const char *content_type;
9291

9392
zend_bool headers_only;

main/main.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -562,7 +562,6 @@ PHP_INI_BEGIN()
562562
STD_PHP_INI_BOOLEAN("allow_url_fopen", "1", PHP_INI_SYSTEM, OnUpdateBool, allow_url_fopen, php_core_globals, core_globals)
563563
STD_PHP_INI_BOOLEAN("allow_url_include", "0", PHP_INI_SYSTEM, OnUpdateBool, allow_url_include, php_core_globals, core_globals)
564564
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)
565-
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)
566565

567566
STD_PHP_INI_ENTRY("realpath_cache_size", "16K", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_size_limit, virtual_cwd_globals, cwd_globals)
568567
STD_PHP_INI_ENTRY("realpath_cache_ttl", "120", PHP_INI_SYSTEM, OnUpdateLong, realpath_cache_ttl, virtual_cwd_globals, cwd_globals)

0 commit comments

Comments
 (0)