Skip to content

Commit 423c70f

Browse files
committed
Merge branch 'slim-postdata-merge'
* slim-postdata-merge: remove unused code tests make reading php://input JIT if enable_post_data_reading=0 revert stream cast fix ZTS build slim post data Conflicts: ext/soap/soap.c ext/standard/php_fopen_wrapper.c main/SAPI.c
2 parents 0f78d86 + 71bee63 commit 423c70f

10 files changed

+392
-50
lines changed

ext/soap/soap.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1580,7 +1580,7 @@ PHP_METHOD(SoapServer, handle)
15801580
array_init_size(&filter_params, 1);
15811581
add_assoc_long_ex(&filter_params, ZEND_STRS("window"), 0x2f); /* ANY WBITS */
15821582

1583-
zf = php_stream_filter_create("zlib.inflate", &filter_params, 0);
1583+
zf = php_stream_filter_create("zlib.inflate", &filter_params, 0 TSRMLS_CC);
15841584
zval_dtor(&filter_params);
15851585

15861586
if (zf) {
@@ -1595,11 +1595,10 @@ PHP_METHOD(SoapServer, handle)
15951595
}
15961596
}
15971597

1598-
doc_request = soap_xmlParseFile("php://input");
1598+
doc_request = soap_xmlParseFile("php://input" TSRMLS_CC);
15991599

16001600
if (zf) {
1601-
php_stream_filter_remove(zf, 1);
1602-
}
1601+
php_stream_filter_remove(zf, 1 TSRMLS_CC);
16031602
} else {
16041603
zval_ptr_dtor(&retval);
16051604
return;

ext/standard/php_fopen_wrapper.c

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ php_stream_ops php_stream_output_ops = {
6363
NULL /* set_option */
6464
};
6565

66+
typedef struct php_stream_input { /* {{{ */
67+
php_stream **body_ptr;
68+
off_t position;
69+
} php_stream_input_t;
70+
/* }}} */
71+
6672
static size_t php_stream_input_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) /* {{{ */
6773
{
6874
return -1;
@@ -71,15 +77,29 @@ static size_t php_stream_input_write(php_stream *stream, const char *buf, size_t
7177

7278
static size_t php_stream_input_read(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */
7379
{
74-
php_stream *inner = stream->abstract;
80+
php_stream_input_t *input = stream->abstract;
81+
size_t read;
7582

76-
if (inner) {
77-
size_t read = php_stream_read(inner, buf, count);
78-
stream->eof = inner->eof;
79-
return read;
83+
if (!SG(post_read) && SG(read_post_bytes) < input->position + count) {
84+
/* read requested data from SAPI */
85+
int read_bytes = sapi_read_post_block(buf, count TSRMLS_CC);
86+
87+
if (read_bytes > 0) {
88+
php_stream_seek(*input->body_ptr, 0, SEEK_END);
89+
php_stream_write(*input->body_ptr, buf, read_bytes);
90+
}
8091
}
8192

82-
return -1;
93+
php_stream_seek(*input->body_ptr, input->position, SEEK_SET);
94+
read = (*input->body_ptr)->ops->read(*input->body_ptr, buf, count TSRMLS_CC);
95+
96+
if (!read || read == (size_t) -1) {
97+
stream->eof = 1;
98+
} else {
99+
input->position += read;
100+
}
101+
102+
return read;
83103
}
84104
/* }}} */
85105

@@ -195,18 +215,23 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa
195215
}
196216

197217
if (!strcasecmp(path, "input")) {
218+
php_stream_input_t *input;
219+
198220
if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) {
199221
if (options & REPORT_ERRORS) {
200222
php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration");
201223
}
202224
return NULL;
203225
}
204-
if (SG(request_info).request_body) {
205-
php_stream_rewind(SG(request_info).request_body);
226+
227+
input = ecalloc(1, sizeof(*input));
228+
if (*(input->body_ptr = &SG(request_info).request_body)) {
229+
php_stream_rewind(*input->body_ptr);
206230
} else {
207-
sapi_read_standard_form_data(TSRMLS_C);
231+
*input->body_ptr = php_stream_temp_create(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE);
208232
}
209-
return php_stream_alloc(&php_stream_input_ops, SG(request_info).request_body, 0, "rb");
233+
234+
return php_stream_alloc(&php_stream_input_ops, input, 0, "rb");
210235
}
211236

212237
if (!strcasecmp(path, "stdin")) {

main/SAPI.c

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,6 @@ 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).request_body) {
184-
php_stream_close(SG(request_info).request_body);
185-
SG(request_info).request_body = NULL;
186-
}*/
187183
efree(SG(request_info).content_type_dup);
188184
SG(request_info).content_type_dup = NULL;
189185
}
@@ -249,43 +245,62 @@ static void sapi_read_post_data(TSRMLS_D)
249245
}
250246
}
251247

252-
253-
SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
248+
SAPI_API int sapi_read_post_block(char *buffer, size_t buflen TSRMLS_DC)
254249
{
255250
int read_bytes;
256251

252+
if (!sapi_module.read_post) {
253+
return -1;
254+
}
255+
256+
read_bytes = sapi_module.read_post(buffer, buflen TSRMLS_CC);
257+
258+
if (read_bytes > 0) {
259+
/* gogo */
260+
SG(read_post_bytes) += read_bytes;
261+
}
262+
if (read_bytes < buflen) {
263+
/* done */
264+
SG(post_read) = 1;
265+
}
266+
267+
return read_bytes;
268+
}
269+
270+
SAPI_API SAPI_POST_READER_FUNC(sapi_read_standard_form_data)
271+
{
257272
if ((SG(post_max_size) > 0) && (SG(request_info).content_length > SG(post_max_size))) {
258273
php_error_docref(NULL TSRMLS_CC, E_WARNING, "POST Content-Length of %ld bytes exceeds the limit of %ld bytes",
259274
SG(request_info).content_length, SG(post_max_size));
260275
return;
261276
}
277+
278+
262279
SG(request_info).request_body = php_stream_temp_create(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE);
263280

264281
if (sapi_module.read_post) {
282+
int read_bytes;
283+
265284
for (;;) {
266285
char buffer[SAPI_POST_BLOCK_SIZE];
267286

268-
read_bytes = sapi_module.read_post(buffer, SAPI_POST_BLOCK_SIZE TSRMLS_CC);
269-
if (read_bytes<=0) {
270-
/* failure */
271-
break;
287+
read_bytes = sapi_read_post_block(buffer, SAPI_POST_BLOCK_SIZE TSRMLS_CC);
288+
289+
if (read_bytes > 0) {
290+
php_stream_write(SG(request_info).request_body, buffer, read_bytes);
272291
}
273-
SG(read_post_bytes) += read_bytes;
274292

275293
if ((SG(post_max_size) > 0) && (SG(read_post_bytes) > SG(post_max_size))) {
276294
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Actual POST length does not match Content-Length, and exceeds %ld bytes", SG(post_max_size));
277295
break;
278296
}
279297

280-
php_stream_write(SG(request_info).request_body, buffer, read_bytes);
281-
282298
if (read_bytes < SAPI_POST_BLOCK_SIZE) {
283299
/* done */
284300
break;
285301
}
286302
}
287-
288-
php_stream_rewind(SG(request_info).request_body);
303+
php_stream_rewind(SG(request_info).request_body);
289304
}
290305
}
291306

@@ -455,21 +470,13 @@ SAPI_API void sapi_activate(TSRMLS_D)
455470

456471
/* Handle request method */
457472
if (SG(server_context)) {
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")) {
462-
/* HTTP POST may contain form data to be processed into variables
463-
* depending on given content type */
464-
sapi_read_post_data(TSRMLS_C);
465-
} else {
466-
/* Any other method with content payload will fill php://input stream.
467-
* It's up to the webserver to decide whether to allow a method or not. */
468-
SG(request_info).content_type_dup = NULL;
469-
if (sapi_module.default_post_reader) {
470-
sapi_module.default_post_reader(TSRMLS_C);
471-
}
472-
}
473+
if (PG(enable_post_data_reading)
474+
&& SG(request_info).content_type
475+
&& SG(request_info).request_method
476+
&& !strcmp(SG(request_info).request_method, "POST")) {
477+
/* HTTP POST may contain form data to be processed into variables
478+
* depending on given content type */
479+
sapi_read_post_data(TSRMLS_C);
473480
} else {
474481
SG(request_info).content_type_dup = NULL;
475482
}
@@ -500,15 +507,15 @@ SAPI_API void sapi_deactivate(TSRMLS_D)
500507
zend_llist_destroy(&SG(sapi_headers).headers);
501508
if (SG(request_info).request_body) {
502509
SG(request_info).request_body = NULL;
503-
} else if (SG(server_context)) {
504-
if(sapi_module.read_post) {
510+
} else if (SG(server_context)) {
511+
if (!SG(post_read)) {
505512
/* make sure we've consumed all request input data */
506513
char dummy[SAPI_POST_BLOCK_SIZE];
507514
int read_bytes;
508515

509-
while((read_bytes = sapi_module.read_post(dummy, sizeof(dummy)-1 TSRMLS_CC)) > 0) {
510-
SG(read_post_bytes) += read_bytes;
511-
}
516+
do {
517+
read_bytes = sapi_read_post_block(dummy, SAPI_POST_BLOCK_SIZE TSRMLS_CC);
518+
} while (SAPI_POST_BLOCK_SIZE == read_bytes);
512519
}
513520
}
514521
if (SG(request_info).auth_user) {

main/SAPI.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ typedef struct _sapi_globals_struct {
120120
sapi_request_info request_info;
121121
sapi_headers_struct sapi_headers;
122122
int64_t read_post_bytes;
123+
unsigned char post_read;
123124
unsigned char headers_sent;
124125
struct stat global_stat;
125126
char *default_mimetype;
@@ -188,7 +189,7 @@ SAPI_API int sapi_add_header_ex(char *header_line, uint header_line_len, zend_bo
188189
SAPI_API int sapi_send_headers(TSRMLS_D);
189190
SAPI_API void sapi_free_header(sapi_header_struct *sapi_header);
190191
SAPI_API void sapi_handle_post(void *arg TSRMLS_DC);
191-
192+
SAPI_API int sapi_read_post_block(char *buffer, size_t buflen TSRMLS_DC);
192193
SAPI_API int sapi_register_post_entries(sapi_post_entry *post_entry TSRMLS_DC);
193194
SAPI_API int sapi_register_post_entry(sapi_post_entry *post_entry TSRMLS_DC);
194195
SAPI_API void sapi_unregister_post_entry(sapi_post_entry *post_entry TSRMLS_DC);

tests/basic/enable_post_data_reading_01.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ var_dump($_FILES);
1111
var_dump($_POST);
1212
var_dump($HTTP_RAW_POST_DATA);
1313
var_dump(file_get_contents("php://input"));
14+
var_dump(file_get_contents("php://input"));
1415
--EXPECTF--
1516
array(0) {
1617
}
@@ -20,3 +21,4 @@ array(0) {
2021
Notice: Undefined variable: HTTP_RAW_POST_DATA in %s on line %d
2122
NULL
2223
string(9) "a=1&b=ZYX"
24+
string(9) "a=1&b=ZYX"

tests/basic/enable_post_data_reading_02.phpt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Content-Type: text/plain-file
1515
var_dump($_FILES);
1616
var_dump($_POST);
1717
var_dump(file_get_contents("php://input"));
18+
var_dump(file_get_contents("php://input"));
1819
--EXPECTF--
1920
array(0) {
2021
}
@@ -26,3 +27,9 @@ Content-Type: text/plain-file
2627

2728
1
2829
-----------------------------20896060251896012921717172737--"
30+
string(%d) "-----------------------------20896060251896012921717172737
31+
Content-Disposition: form-data; name="file1"; filename="file1.txt"
32+
Content-Type: text/plain-file
33+
34+
1
35+
-----------------------------20896060251896012921717172737--"

tests/basic/enable_post_data_reading_03.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var_dump($_FILES);
1212
var_dump($_POST);
1313
var_dump($HTTP_RAW_POST_DATA);
1414
var_dump(file_get_contents("php://input"));
15+
var_dump(file_get_contents("php://input"));
1516
--EXPECTF--
1617
array(0) {
1718
}
@@ -21,3 +22,4 @@ array(0) {
2122
Notice: Undefined variable: HTTP_RAW_POST_DATA in %s on line %d
2223
NULL
2324
string(9) "a=1&b=ZYX"
25+
string(9) "a=1&b=ZYX"

tests/basic/enable_post_data_reading_04.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ var_dump($_FILES);
1212
var_dump($_POST);
1313
var_dump($HTTP_RAW_POST_DATA);
1414
var_dump(file_get_contents("php://input"));
15+
var_dump(file_get_contents("php://input"));
1516
--EXPECTF--
1617
array(0) {
1718
}
@@ -21,3 +22,4 @@ array(0) {
2122
Notice: Undefined variable: HTTP_RAW_POST_DATA in %s on line %d
2223
NULL
2324
string(9) "a=1&b=ZYX"
25+
string(9) "a=1&b=ZYX"
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
enable_post_data_reading: using multiple input streams
3+
--INI--
4+
enable_post_data_reading=0
5+
max_execution_time=2
6+
--POST_RAW--
7+
Content-Type: application/unknown
8+
One line of data
9+
--FILE--
10+
<?php
11+
echo "Test\n";
12+
13+
$f1 = fopen("php://input", "r");
14+
$f2 = fopen("php://input", "r");
15+
16+
while (!feof($f1) && !feof($f2)) {
17+
echo fgetc($f1), fgetc($f2);
18+
}
19+
20+
?>
21+
22+
Done
23+
--EXPECT--
24+
Test
25+
OOnnee lliinnee ooff ddaattaa
26+
Done

0 commit comments

Comments
 (0)