Skip to content

Commit 449d4c0

Browse files
committed
make reading php://input JIT if enable_post_data_reading=0
1 parent e3e4d1b commit 449d4c0

File tree

3 files changed

+92
-42
lines changed

3 files changed

+92
-42
lines changed

ext/standard/php_fopen_wrapper.c

Lines changed: 49 additions & 6 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,20 +77,52 @@ 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;
82+
//fprintf(stderr, "Attempt to read %lu bytes (%lu)\n", count, SG(read_post_bytes));
83+
84+
if (!SG(post_read) && SG(read_post_bytes) < input->position + count) {
85+
/* read requested data from SAPI */
86+
int read_bytes = sapi_read_post_block(buf, count TSRMLS_CC);
87+
88+
//fprintf(stderr, "Did read %d bytes\n", read_bytes);
89+
if (read_bytes > 0) {
90+
php_stream_seek(*input->body_ptr, 0, SEEK_END);
91+
php_stream_write(*input->body_ptr, buf, read_bytes);
92+
}
93+
}
94+
95+
php_stream_seek(*input->body_ptr, input->position, SEEK_SET);
96+
read = (*input->body_ptr)->ops->read(*input->body_ptr, buf, count TSRMLS_CC);
97+
98+
if (!read || read == (size_t) -1) {
99+
stream->eof = 1;
100+
} else {
101+
input->position += read;
102+
}
103+
104+
return read;
105+
}
106+
/* }}} */
107+
108+
static size_t php_stream_input_read_x(php_stream *stream, char *buf, size_t count TSRMLS_DC) /* {{{ */
109+
{
110+
php_stream_input_t *input = stream->abstract;
111+
php_stream *inner = *input->body_ptr;
75112

76113
if (inner && inner->ops->read) {
77114
size_t read = inner->ops->read(inner, buf, count TSRMLS_CC);
78115
stream->eof = inner->eof;
79116
return read;
80117
}
81-
82118
return -1;
83119
}
84120
/* }}} */
85121

86122
static int php_stream_input_close(php_stream *stream, int close_handle TSRMLS_DC) /* {{{ */
87123
{
124+
efree(stream->abstract);
125+
88126
return 0;
89127
}
90128
/* }}} */
@@ -193,18 +231,23 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa
193231
}
194232

195233
if (!strcasecmp(path, "input")) {
234+
php_stream_input_t *input;
235+
196236
if ((options & STREAM_OPEN_FOR_INCLUDE) && !PG(allow_url_include) ) {
197237
if (options & REPORT_ERRORS) {
198238
php_error_docref(NULL TSRMLS_CC, E_WARNING, "URL file-access is disabled in the server configuration");
199239
}
200240
return NULL;
201241
}
202-
if (SG(request_info).request_body) {
203-
php_stream_rewind(SG(request_info).request_body);
242+
243+
input = ecalloc(1, sizeof(*input));
244+
if (*(input->body_ptr = &SG(request_info).request_body)) {
245+
php_stream_rewind(*input->body_ptr);
204246
} else {
205-
sapi_read_standard_form_data(TSRMLS_C);
247+
*input->body_ptr = php_stream_temp_create(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE);
206248
}
207-
return php_stream_alloc(&php_stream_input_ops, SG(request_info).request_body, 0, "rb");
249+
250+
return php_stream_alloc(&php_stream_input_ops, input, 0, "rb");
208251
}
209252

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

main/SAPI.c

Lines changed: 41 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,61 @@ 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+
262278
SG(request_info).request_body = php_stream_temp_create(TEMP_STREAM_DEFAULT, SAPI_POST_BLOCK_SIZE);
263279

264280
if (sapi_module.read_post) {
281+
int read_bytes;
282+
265283
for (;;) {
266284
char buffer[SAPI_POST_BLOCK_SIZE];
267285

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

275292
if ((SG(post_max_size) > 0) && (SG(read_post_bytes) > SG(post_max_size))) {
276293
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Actual POST length does not match Content-Length, and exceeds %ld bytes", SG(post_max_size));
277294
break;
278295
}
279296

280-
php_stream_write(SG(request_info).request_body, buffer, read_bytes);
281-
282297
if (read_bytes < SAPI_POST_BLOCK_SIZE) {
283298
/* done */
284299
break;
285300
}
286301
}
287-
288-
php_stream_rewind(SG(request_info).request_body);
302+
php_stream_rewind(SG(request_info).request_body);
289303
}
290304
}
291305

@@ -455,21 +469,13 @@ SAPI_API void sapi_activate(TSRMLS_D)
455469

456470
/* Handle request method */
457471
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-
}
472+
if (PG(enable_post_data_reading)
473+
&& SG(request_info).content_type
474+
&& SG(request_info).request_method
475+
&& !strcmp(SG(request_info).request_method, "POST")) {
476+
/* HTTP POST may contain form data to be processed into variables
477+
* depending on given content type */
478+
sapi_read_post_data(TSRMLS_C);
473479
} else {
474480
SG(request_info).content_type_dup = NULL;
475481
}
@@ -500,15 +506,15 @@ SAPI_API void sapi_deactivate(TSRMLS_D)
500506
zend_llist_destroy(&SG(sapi_headers).headers);
501507
if (SG(request_info).request_body) {
502508
SG(request_info).request_body = NULL;
503-
} else if (SG(server_context)) {
504-
if(sapi_module.read_post) {
509+
} else if (SG(server_context)) {
510+
if (!SG(post_read)) {
505511
/* make sure we've consumed all request input data */
506512
char dummy[SAPI_POST_BLOCK_SIZE];
507513
int read_bytes;
508514

509-
while((read_bytes = sapi_module.read_post(dummy, sizeof(dummy)-1 TSRMLS_CC)) > 0) {
510-
SG(read_post_bytes) += read_bytes;
511-
}
515+
do {
516+
read_bytes = sapi_read_post_block(dummy, SAPI_POST_BLOCK_SIZE TSRMLS_CC);
517+
} while (SAPI_POST_BLOCK_SIZE == read_bytes);
512518
}
513519
}
514520
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);

0 commit comments

Comments
 (0)