[packages/php-suhosin] Rel 2. Port CVE-2026-109618/109619, CVE-2023-0662 and CVE-2024-8925 fixes to suhosin's own copy of t
arekm
arekm at pld-linux.org
Thu Oct 22 10:39:07 CEST 2026
commit c8c667f76c94fb585a9af122dfa1d2ed55fba33d
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Thu Oct 22 10:36:29 2026 +0200
Rel 2. Port CVE-2026-109618/109619, CVE-2023-0662 and CVE-2024-8925 fixes to suhosin's own copy of the PHP POST parser; reset request state in post-deactivate.
php-suhosin-bug78875.patch | 38 ++++++
php-suhosin-cve-2023-0662.patch | 70 ++++++++++
php-suhosin-cve-2024-8925.patch | 20 +++
php-suhosin-cve-2026-109618.patch | 66 ++++++++++
php-suhosin-extract-globals.patch | 20 +++
php-suhosin-request-state.patch | 73 +++++++++++
php-suhosin-rfc1867-header-leak.patch | 23 ++++
php-suhosin-rfc1867-php-sync.patch | 207 ++++++++++++++++++++++++++++++
php-suhosin-upload-totalname-length.patch | 15 +++
php-suhosin.spec | 22 +++-
10 files changed, 552 insertions(+), 2 deletions(-)
---
diff --git a/php-suhosin.spec b/php-suhosin.spec
index 63089a9..162efc2 100644
--- a/php-suhosin.spec
+++ b/php-suhosin.spec
@@ -5,11 +5,20 @@ Summary(pl.UTF-8): Zaawansowany system zabezpieczeń dla instalacji PHP
Name: %{php_name}-%{modname}
# for PHP 5.3, see PHP_5_3 branch
Version: 0.9.38
-Release: 1
+Release: 2
License: PHP 3.01
Group: Development/Languages/PHP
-Source0: http://download.suhosin.org/%{modname}-%{version}.tar.gz
+Source0: https://download.suhosin.org/%{modname}-%{version}.tar.gz
# Source0-md5: 0c26402752b0aff69e4b891f062a52bf
+Patch0: php-suhosin-rfc1867-php-sync.patch
+Patch1: php-suhosin-bug78875.patch
+Patch2: php-suhosin-cve-2023-0662.patch
+Patch3: php-suhosin-cve-2024-8925.patch
+Patch4: php-suhosin-rfc1867-header-leak.patch
+Patch5: php-suhosin-cve-2026-109618.patch
+Patch6: php-suhosin-request-state.patch
+Patch7: php-suhosin-extract-globals.patch
+Patch8: php-suhosin-upload-totalname-length.patch
URL: http://www.suhosin.org/stories/
BuildRequires: %{php_name}-devel >= 4:5.4
BuildRequires: rpmbuild(macros) >= 1.650
@@ -39,6 +48,15 @@ ZendOptimizer.
%prep
%setup -q -n suhosin-%{version}
+%patch -P0 -p1
+%patch -P1 -p1
+%patch -P2 -p1
+%patch -P3 -p1
+%patch -P4 -p1
+%patch -P5 -p1
+%patch -P6 -p1
+%patch -P7 -p1
+%patch -P8 -p1
%build
phpize
diff --git a/php-suhosin-bug78875.patch b/php-suhosin-bug78875.patch
new file mode 100644
index 0000000..98428bf
--- /dev/null
+++ b/php-suhosin-bug78875.patch
@@ -0,0 +1,38 @@
+PHP bug #78875/#78876 (long names cause OOM) in suhosin's copy of rfc1867.c,
+same change as php-bug78875.patch in php56
+
+diff --git suhosin-0.9.38.orig/rfc1867_new.c suhosin-0.9.38/rfc1867_new.c
+index 4897d76..50b48f7 100644
+--- suhosin-0.9.38.orig/rfc1867_new.c
++++ suhosin-0.9.38/rfc1867_new.c
+@@ -609,9 +609,9 @@ static void *php_ap_memstr(char *haystack, int haystacklen, char *needle, int ne
+ }
+
+ /* read until a boundary condition */
+-static int multipart_buffer_read(multipart_buffer *self, char *buf, int bytes, int *end TSRMLS_DC)
++static unsigned int multipart_buffer_read(multipart_buffer *self, char *buf, unsigned int bytes, int *end TSRMLS_DC)
+ {
+- int len, max;
++ unsigned int len, max;
+ char *bound;
+
+ /* fill buffer if needed */
+@@ -658,7 +658,7 @@ static int multipart_buffer_read(multipart_buffer *self, char *buf, int bytes, i
+ static char *multipart_buffer_read_body(multipart_buffer *self, unsigned int *len TSRMLS_DC)
+ {
+ char buf[FILLUNIT], *out=NULL;
+- int total_bytes=0, read_bytes=0;
++ unsigned int total_bytes=0, read_bytes=0;
+
+ while((read_bytes = multipart_buffer_read(self, buf, sizeof(buf), NULL TSRMLS_CC))) {
+ out = erealloc(out, total_bytes + read_bytes + 1);
+@@ -684,7 +684,8 @@ 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, cancel_upload = 0, is_arr_upload = 0, array_len = 0;
++ int boundary_len = 0, cancel_upload = 0, is_arr_upload = 0;
++ unsigned int 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;
diff --git a/php-suhosin-cve-2023-0662.patch b/php-suhosin-cve-2023-0662.patch
new file mode 100644
index 0000000..7d740a7
--- /dev/null
+++ b/php-suhosin-cve-2023-0662.patch
@@ -0,0 +1,70 @@
+CVE-2023-0662 (unbounded number of multipart parts) in suhosin's copy of rfc1867.c;
+max_multipart_body_parts is honoured when the PHP core provides it
+
+diff --git suhosin-0.9.38.orig/rfc1867_new.c suhosin-0.9.38/rfc1867_new.c
+index 50b48f7..cecb5b4 100644
+--- suhosin-0.9.38.orig/rfc1867_new.c
++++ suhosin-0.9.38/rfc1867_new.c
+@@ -680,6 +680,18 @@ static char *multipart_buffer_read_body(multipart_buffer *self, unsigned int *le
+ *
+ */
+
++/* max_multipart_body_parts exists only in a PHP carrying the CVE-2023-0662 fix,
++ * INI_INT() of a missing entry is 0 and would reject every part */
++static int suhosin_max_multipart_body_parts(TSRMLS_D)
++{
++ zend_ini_entry *ini_entry;
++
++ if (zend_hash_find(EG(ini_directives), "max_multipart_body_parts", sizeof("max_multipart_body_parts"), (void **) &ini_entry) == FAILURE) {
++ return -1;
++ }
++ return INI_INT("max_multipart_body_parts");
++}
++
+ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */
+ {
+ char *boundary, *s = NULL, *boundary_end = NULL, *start_arr = NULL, *array_index = NULL;
+@@ -697,6 +709,7 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */
+ void *event_extra_data = NULL;
+ unsigned int llen = 0;
+ int upload_cnt = INI_INT("max_file_uploads");
++ int body_parts_cnt = suhosin_max_multipart_body_parts(TSRMLS_C);
+ const zend_encoding *internal_encoding = zend_multibyte_get_internal_encoding(TSRMLS_C);
+ php_rfc1867_getword_t getword;
+ php_rfc1867_getword_conf_t getword_conf;
+@@ -718,6 +731,11 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */
+ return;
+ }
+
++ if (body_parts_cnt < 0) {
++ body_parts_cnt = PG(max_input_vars) + upload_cnt;
++ }
++ int body_parts_limit = body_parts_cnt;
++
+ /* Get the boundary */
+ boundary = strstr(content_type_dup, "boundary");
+ if (!boundary) {
+@@ -802,6 +820,11 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */
+ char *pair = NULL;
+ int end = 0;
+
++ if (--body_parts_cnt < 0) {
++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Multipart body parts limit exceeded %d. To increase the limit change max_multipart_body_parts in php.ini.", body_parts_limit);
++ goto fileupload_done;
++ }
++
+ while (isspace(*cd)) {
+ ++cd;
+ }
+@@ -932,7 +955,10 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */
+ skip_upload = 1;
+ } else if (upload_cnt <= 0) {
+ skip_upload = 1;
+- sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded");
++ if (upload_cnt == 0) {
++ --upload_cnt;
++ sapi_module.sapi_error(E_WARNING, "Maximum number of allowable file uploads has been exceeded");
++ }
+ }
+
+ /* Return with an error if the posted data is garbled */
diff --git a/php-suhosin-cve-2024-8925.patch b/php-suhosin-cve-2024-8925.patch
new file mode 100644
index 0000000..e82d4b3
--- /dev/null
+++ b/php-suhosin-cve-2024-8925.patch
@@ -0,0 +1,20 @@
+CVE-2024-8925 (boundaries larger than the read buffer) in suhosin's copy of rfc1867.c
+
+diff --git suhosin-0.9.38.orig/rfc1867_new.c suhosin-0.9.38/rfc1867_new.c
+index cecb5b4..362229e 100644
+--- suhosin-0.9.38.orig/rfc1867_new.c
++++ suhosin-0.9.38/rfc1867_new.c
+@@ -774,6 +774,13 @@ SAPI_POST_HANDLER_FUNC(suhosin_rfc1867_post_handler) /* {{{ */
+ boundary_len = boundary_end-boundary;
+ }
+
++ /* Boundaries larger than FILLUNIT-strlen("\r\n--") characters lead to
++ * erroneous parsing */
++ if (boundary_len > FILLUNIT-strlen("\r\n--")) {
++ sapi_module.sapi_error(E_WARNING, "Boundary too large in multipart/form-data POST data");
++ return;
++ }
++
+ /* Initialize the buffer */
+ if (!(mbuff = multipart_buffer_new(boundary, boundary_len TSRMLS_CC))) {
+ sapi_module.sapi_error(E_WARNING, "Unable to initialize the input buffer");
diff --git a/php-suhosin-cve-2026-109618.patch b/php-suhosin-cve-2026-109618.patch
new file mode 100644
index 0000000..4c75ebd
--- /dev/null
+++ b/php-suhosin-cve-2026-109618.patch
@@ -0,0 +1,66 @@
+CVE-2026-109618: multipart parser part of the PHP fix, ported to suhosin's copy of
+rfc1867.c, which replaces the patched one in PHP: keep only the headers used, size_t lengths
+https://github.com/php/php-src/security/advisories/GHSA-w8hw-w9fx-j79w
+
+diff --git suhosin-0.9.38.orig/rfc1867_new.c suhosin-0.9.38/rfc1867_new.c
+index 8bb9f6e..cd0847f 100644
+--- suhosin-0.9.38.orig/rfc1867_new.c
++++ suhosin-0.9.38/rfc1867_new.c
+@@ -386,6 +386,14 @@ static int find_boundary(multipart_buffer *self, char *boundary TSRMLS_DC)
+ return 0;
+ }
+
++static zend_bool php_mime_should_save_hdr(const char *name)
++{
++ return !strcasecmp(name, "Content-Disposition")
++ || !strcasecmp(name, "Content-Type");
++}
++
++static char *php_mime_get_hdr_value(zend_llist header, char *key);
++
+ /* parse headers */
+ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header TSRMLS_DC)
+ {
+@@ -431,10 +439,15 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header T
+ }
+
+ *value = '\0';
+- do { value++; } while(isspace(*value));
+-
+- key = estrdup(line);
+- smart_str_appends(&buf_value, value);
++ /* Keep only headers we use, and ignore duplicates */
++ if (!php_mime_should_save_hdr(line)
++ || php_mime_get_hdr_value(*header, line)) {
++ key = NULL;
++ } else {
++ key = estrdup(line);
++ do { value++; } while (isspace((unsigned char)*value));
++ smart_str_appends(&buf_value, value);
++ }
+
+ newlines = 0;
+
+@@ -518,11 +531,11 @@ static char *php_ap_getword(const zend_encoding *encoding, char **line, char sto
+ return res;
+ }
+
+-static char *substring_conf(char *start, int len, char quote)
++static char *substring_conf(char *start, size_t len, char quote)
+ {
+ char *result = emalloc(len + 1);
+ char *resp = result;
+- int i;
++ size_t i;
+
+ for (i = 0; i < len && start[i] != quote; ++i) {
+ if (start[i] == '\\' && (start[i + 1] == '\\' || (quote && start[i + 1] == quote))) {
+@@ -557,7 +570,7 @@ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str TSRMLS
+ while (*strend && !isspace(*strend)) {
+ ++strend;
+ }
+- return substring_conf(str, strend - str, 0);
++ return substring_conf(str, (size_t)(strend - str), 0);
+ }
+ }
+
diff --git a/php-suhosin-extract-globals.patch b/php-suhosin-extract-globals.patch
new file mode 100644
index 0000000..46e98ee
--- /dev/null
+++ b/php-suhosin-extract-globals.patch
@@ -0,0 +1,20 @@
+suhosin's extract() compared the name length without the NUL against sizeof(), so the
+$GLOBALS and $this protection of PHP's extract() never matched
+
+diff --git suhosin-0.9.38.orig/ex_imp.c suhosin-0.9.38/ex_imp.c
+index b5ca46a..da6c668 100644
+--- suhosin-0.9.38.orig/ex_imp.c
++++ suhosin-0.9.38/ex_imp.c
+@@ -163,10 +163,10 @@ PHP_FUNCTION(suhosin_extract)
+
+ case EXTR_OVERWRITE:
+ /* GLOBALS protection */
+- if (var_exists && var_name_len == sizeof("GLOBALS") && !strcmp(var_name, "GLOBALS")) {
++ if (var_exists && var_name_len == sizeof("GLOBALS")-1 && !strcmp(var_name, "GLOBALS")) {
+ break;
+ }
+- if (var_exists && var_name_len == sizeof("this") && !strcmp(var_name, "this") && EG(scope) && EG(scope)->name_length != 0) {
++ if (var_exists && var_name_len == sizeof("this")-1 && !strcmp(var_name, "this") && EG(scope) && EG(scope)->name_length != 0) {
+ break;
+ }
+ ZVAL_STRINGL(&final_name, var_name, var_name_len, 1);
diff --git a/php-suhosin-request-state.patch b/php-suhosin-request-state.patch
new file mode 100644
index 0000000..c1b6ad7
--- /dev/null
+++ b/php-suhosin-request-state.patch
@@ -0,0 +1,73 @@
+CVE-2026-109619 class: input filter state, decrypted cookie pointers and do_not_scan
+were reset only in RSHUTDOWN, which PHP skips after a failed request startup
+https://github.com/php/php-src/security/advisories/GHSA-6wmf-4rv5-p3rp
+
+diff --git suhosin-0.9.38.orig/php_suhosin.h suhosin-0.9.38/php_suhosin.h
+index f82c460..1676c3e 100644
+--- suhosin-0.9.38.orig/php_suhosin.h
++++ suhosin-0.9.38/php_suhosin.h
+@@ -65,7 +65,7 @@ extern zend_module_entry suhosin_module_entry;
+ PHP_MINIT_FUNCTION(suhosin);
+ PHP_MSHUTDOWN_FUNCTION(suhosin);
+ PHP_RINIT_FUNCTION(suhosin);
+-PHP_RSHUTDOWN_FUNCTION(suhosin);
++ZEND_MODULE_POST_ZEND_DEACTIVATE_D(suhosin);
+ PHP_MINFO_FUNCTION(suhosin);
+
+ #include "ext/standard/basic_functions.h"
+diff --git suhosin-0.9.38.orig/suhosin.c suhosin-0.9.38/suhosin.c
+index 9e2d017..5059527 100644
+--- suhosin-0.9.38.orig/suhosin.c
++++ suhosin-0.9.38/suhosin.c
+@@ -754,12 +754,14 @@ zend_module_entry suhosin_module_entry = {
+ PHP_MINIT(suhosin),
+ PHP_MSHUTDOWN(suhosin),
+ PHP_RINIT(suhosin),
+- PHP_RSHUTDOWN(suhosin),
++ NULL,
+ PHP_MINFO(suhosin),
+ #if ZEND_MODULE_API_NO >= 20010901
+ SUHOSIN_EXT_VERSION, /* Replace with version number for your extension */
+ #endif
+- STANDARD_MODULE_PROPERTIES
++ NO_MODULE_GLOBALS,
++ ZEND_MODULE_POST_ZEND_DEACTIVATE_N(suhosin),
++ STANDARD_MODULE_PROPERTIES_EX
+ };
+ /* }}} */
+
+@@ -1091,16 +1093,18 @@ PHP_RINIT_FUNCTION(suhosin)
+ /* }}} */
+
+
+-/* {{{ PHP_RSHUTDOWN_FUNCTION
++/* {{{ ZEND_MODULE_POST_ZEND_DEACTIVATE_D
+ */
+-PHP_RSHUTDOWN_FUNCTION(suhosin)
++ZEND_MODULE_POST_ZEND_DEACTIVATE_D(suhosin)
+ {
+- SDEBUG("(RSHUTDOWN)");
++ TSRMLS_FETCH();
++
++ SDEBUG("(POST_DEACTIVATE)");
+
+- /* We need to clear the input filtering
+- variables in the request shutdown
+- because input filtering is done before
+- RINIT */
++ /* Input filtering runs before RINIT, so this state must be cleared
++ even when RINIT never ran: PHP skips RSHUTDOWN after a failed
++ request startup, but always calls post-deactivate while the
++ request heap still exists. */
+
+ SUHOSIN_G(cur_request_variables) = 0;
+ SUHOSIN_G(cur_cookie_vars) = 0;
+@@ -1119,6 +1123,8 @@ PHP_RSHUTDOWN_FUNCTION(suhosin)
+ SUHOSIN_G(no_more_uploads) = 0;
+
+ SUHOSIN_G(abort_request) = 0;
++ SUHOSIN_G(already_scanned) = 0;
++ SUHOSIN_G(do_not_scan) = 0;
+
+ if (SUHOSIN_G(reseed_every_request)) {
+ SUHOSIN_G(r_is_seeded) = 0;
diff --git a/php-suhosin-rfc1867-header-leak.patch b/php-suhosin-rfc1867-header-leak.patch
new file mode 100644
index 0000000..6cb2d1e
--- /dev/null
+++ b/php-suhosin-rfc1867-header-leak.patch
@@ -0,0 +1,23 @@
+https://github.com/sektioneins/suhosin/commit/1a2cb68a84: header value leaked when
+suhosin.upload.max_newlines is exceeded
+
+diff --git suhosin-0.9.38.orig/rfc1867_new.c suhosin-0.9.38/rfc1867_new.c
+index 362229e..8bb9f6e 100644
+--- suhosin-0.9.38.orig/rfc1867_new.c
++++ suhosin-0.9.38/rfc1867_new.c
+@@ -439,13 +439,14 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header T
+ newlines = 0;
+
+ } 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;
+ suhosin_log(S_FILES, "configured maximum number of newlines in RFC1867 MIME headers limit exceeded - dropping rest of upload");
++ smart_str_free(&buf_value);
+ return 0;
+ }
++ smart_str_appends(&buf_value, line);
+
+ } else {
+ continue;
diff --git a/php-suhosin-rfc1867-php-sync.patch b/php-suhosin-rfc1867-php-sync.patch
new file mode 100644
index 0000000..3161301
--- /dev/null
+++ b/php-suhosin-rfc1867-php-sync.patch
@@ -0,0 +1,207 @@
+suhosin's copy of the PHP multipart parser predates PHP 5.6.9: quadratic header continuation
+parsing (CVE-2015-4024) and 32-bit file sizes; upstream 356da61627 without its revert of the
+input filter length, which upstream undid in 72c613f619
+
+diff --git suhosin-0.9.38.orig/rfc1867_new.c suhosin-0.9.38/rfc1867_new.c
+index dfdc1d9..4897d76 100644
+--- suhosin-0.9.38.orig/rfc1867_new.c
++++ suhosin-0.9.38/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;
+@@ -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);
+ }
diff --git a/php-suhosin-upload-totalname-length.patch b/php-suhosin-upload-totalname-length.patch
new file mode 100644
index 0000000..235440d
--- /dev/null
+++ b/php-suhosin-upload-totalname-length.patch
@@ -0,0 +1,15 @@
+suhosin.post.max_totalname_length was compared with the base name length for upload fields
+
+diff --git suhosin-0.9.38.orig/ufilter.c suhosin-0.9.38/ufilter.c
+index 203d76c..7a83ede 100644
+--- suhosin-0.9.38.orig/ufilter.c
++++ suhosin-0.9.38/ufilter.c
+@@ -73,7 +73,7 @@ static int check_fileupload_varname(char *varname TSRMLS_DC)
+ goto return_failure;
+ }
+ }
+- if (SUHOSIN_G(max_post_totalname_length) && SUHOSIN_G(max_post_totalname_length) < var_len) {
++ if (SUHOSIN_G(max_post_totalname_length) && SUHOSIN_G(max_post_totalname_length) < total_len) {
+ suhosin_log(S_FILES, "configured POST variable total name length limit exceeded - dropped variable '%s'", var);
+ if (!SUHOSIN_G(simulation)) {
+ goto return_failure;
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/php-suhosin.git/commitdiff/c8c667f76c94fb585a9af122dfa1d2ed55fba33d
More information about the pld-cvs-commit
mailing list