From 356da616277c73f7c26cd16b53b6d47b8b7b2cb3 Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Tue, 1 Mar 2016 15:33:31 +0100 Subject: merged changes to RFC1867 code (closes #86) --- Changelog | 1 + rfc1867_new.c | 109 +++++++++++++++++++++++++++++++++++++++------------------- 2 files changed, 75 insertions(+), 35 deletions(-) diff --git a/Changelog b/Changelog index fbf5709..874e00b 100644 --- a/Changelog +++ b/Changelog @@ -3,6 +3,7 @@ - removed dead code - better debian integration - fixed perdir checks + - merged PHP changes to RFC1867 code 2015-05-21 - 0.9.38 - removed code compatibility for PHP <5.4 (lots of code + ifdefs) diff --git a/rfc1867_new.c b/rfc1867_new.c index 318e5a6..e03de44 100644 --- a/rfc1867_new.c +++ b/rfc1867_new.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2013 The PHP Group | + | Copyright (c) 1997-2016 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -34,7 +34,12 @@ #include "php_suhosin.h" #include "suhosin_rfc1867.h" #include "ext/standard/php_string.h" +#include "ext/standard/php_smart_str.h" +#if defined(PHP_WIN32) && !defined(HAVE_ATOLL) +# define atoll(s) _atoi64(s) +# define HAVE_ATOLL 1 +#endif #define DEBUG_FILE_UPLOAD ZEND_DEBUG @@ -385,8 +390,12 @@ static int find_boundary(multipart_buffer *self, char *boundary TSRMLS_DC) static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header TSRMLS_DC) { char *line; - mime_header_entry prev_entry = {0}, entry; - int prev_len, cur_len; + mime_header_entry entry = {0}; + smart_str buf_value = {0}; + char *key = NULL; + + // mime_header_entry prev_entry = {0}; + // int prev_len, cur_len; int newlines = 0; /* didn't find boundary, abort */ @@ -399,11 +408,10 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header T while( (line = get_line(self TSRMLS_CC)) && line[0] != '\0' ) { /* add header to table */ - char *key = line; char *value = NULL; if (php_rfc1867_encoding_translation(TSRMLS_C)) { - self->input_encoding = zend_multibyte_encoding_detector((const unsigned char *)line, strlen(line), self->detect_order, self->detect_order_size TSRMLS_CC); + self->input_encoding = zend_multibyte_encoding_detector((unsigned char *)line, strlen(line), self->detect_order, self->detect_order_size TSRMLS_CC); } /* space in the beginning means same header */ @@ -412,24 +420,26 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header T } if (value) { - *value = 0; - do { value++; } while(isspace(*value)); - - entry.value = estrdup(value); - entry.key = estrdup(key); - newlines = 0; + if(buf_value.c && key) { + /* new entry, add the old one to the list */ + smart_str_0(&buf_value); + entry.key = key; + entry.value = buf_value.c; + zend_llist_add_element(header, &entry); + buf_value.c = NULL; + key = NULL; + } - } else if (zend_llist_count(header)) { /* If no ':' on the line, add to previous line */ + *value = '\0'; + do { value++; } while(isspace(*value)); - prev_len = strlen(prev_entry.value); - cur_len = strlen(line); + key = estrdup(line); + smart_str_appends(&buf_value, value); - entry.value = emalloc(prev_len + cur_len + 1); - memcpy(entry.value, prev_entry.value, prev_len); - memcpy(entry.value + prev_len, line, cur_len); - entry.value[cur_len + prev_len] = '\0'; + newlines = 0; - entry.key = estrdup(prev_entry.key); + } else if (buf_value.c) { /* If no ':' on the line, add to previous line */ + smart_str_appends(&buf_value, line); newlines++; if (newlines > SUHOSIN_G(upload_max_newlines)) { SUHOSIN_G(abort_request) = 1; @@ -437,13 +447,16 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header T return 0; } - zend_llist_remove_tail(header); } else { continue; } - + } + if(buf_value.c && key) { + /* add the last one to the list */ + smart_str_0(&buf_value); + entry.key = key; + entry.value = buf_value.c; zend_llist_add_element(header, &entry); - prev_entry = entry; } return 1; @@ -671,8 +684,9 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */ { char *boundary, *s = NULL, *boundary_end = NULL, *start_arr = NULL, *array_index = NULL; char *temp_filename = NULL, *lbuf = NULL, *abuf = NULL; - int boundary_len = 0, total_bytes = 0, cancel_upload = 0, is_arr_upload = 0, array_len = 0; - int max_file_size = 0, skip_upload = 0, anonindex = 0, is_anonymous; + int boundary_len = 0, cancel_upload = 0, is_arr_upload = 0, array_len = 0; + int64_t total_bytes = 0, max_file_size = 0; + int skip_upload = 0, anonindex = 0, is_anonymous; zval *http_post_files = NULL; HashTable *uploaded_files = NULL; multipart_buffer *mbuff; @@ -864,7 +878,7 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */ continue; } - if (++count <= PG(max_input_vars) && sapi_module.input_filter(PARSE_POST, param, &value, new_val_len, &new_val_len TSRMLS_CC)) { + if (++count <= PG(max_input_vars) && sapi_module.input_filter(PARSE_POST, param, &value, value_len, &new_val_len TSRMLS_CC)) { if (&suhosin_rfc1867_filter != NULL) { multipart_event_formdata event_formdata; size_t newlength = new_val_len; @@ -886,7 +900,7 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */ if (count == PG(max_input_vars) + 1) { 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)); } - + if (&suhosin_rfc1867_filter != NULL) { multipart_event_formdata event_formdata; @@ -900,7 +914,11 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */ } if (!strcasecmp(param, "MAX_FILE_SIZE")) { - max_file_size = atol(value); +#ifdef HAVE_ATOLL + max_file_size = atoll(value); +#else + max_file_size = strtoll(value, NULL, 10); +#endif } efree(param); @@ -1212,17 +1230,32 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */ { zval file_size, error_type; + int size_overflow = 0; + char file_size_buf[65]; - error_type.value.lval = cancel_upload; - error_type.type = IS_LONG; + ZVAL_LONG(&error_type, cancel_upload); /* Add $foo[error] */ if (cancel_upload) { - file_size.value.lval = 0; - file_size.type = IS_LONG; + ZVAL_LONG(&file_size, 0); } else { - file_size.value.lval = total_bytes; - file_size.type = IS_LONG; + if (total_bytes > LONG_MAX) { +#ifdef PHP_WIN32 + if (_i64toa_s(total_bytes, file_size_buf, 65, 10)) { + file_size_buf[0] = '0'; + file_size_buf[1] = '\0'; + } +#else + { + int __len = snprintf(file_size_buf, 65, "%lld", total_bytes); + file_size_buf[__len] = '\0'; + } +#endif + size_overflow = 1; + + } else { + ZVAL_LONG(&file_size, total_bytes); + } } if (is_arr_upload) { @@ -1239,7 +1272,10 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */ snprintf(lbuf, llen, "%s_size", param); } if (!is_anonymous) { - safe_php_register_variable_ex(lbuf, &file_size, NULL, 0 TSRMLS_CC); + if (size_overflow) { + ZVAL_STRING(&file_size, file_size_buf, 1); + } + safe_php_register_variable_ex(lbuf, &file_size, NULL, size_overflow TSRMLS_CC); } /* Add $foo[size] */ @@ -1248,7 +1284,10 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */ } else { snprintf(lbuf, llen, "%s[size]", param); } - register_http_post_files_variable_ex(lbuf, &file_size, http_post_files, 0 TSRMLS_CC); + if (size_overflow) { + ZVAL_STRING(&file_size, file_size_buf, 1); + } + register_http_post_files_variable_ex(lbuf, &file_size, http_post_files, size_overflow TSRMLS_CC); } efree(param); } -- cgit v1.3