[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