From c8724cde260e6c8bab4aefffffa1aa46f92a57ee Mon Sep 17 00:00:00 2001 From: Ben Fuhrmannek Date: Sat, 11 Oct 2014 10:25:59 +0200 Subject: fixed utf8 detection + made feature experimental --- php_suhosin.h | 2 ++ suhosin.c | 4 +++- suhosin.ini | 10 ++-------- .../suhosin_upload_disallow_binary_utf8.phpt | 4 +++- .../suhosin_upload_disallow_binary_utf8fail.phpt | 4 +++- .../filter/suhosin_upload_remove_binary_utf8.phpt | 4 +++- .../suhosin_upload_remove_binary_utf8fail.phpt | 4 +++- ufilter.c | 22 +++++++++++++++------- 8 files changed, 34 insertions(+), 20 deletions(-) diff --git a/php_suhosin.h b/php_suhosin.h index d567877..df7c877 100644 --- a/php_suhosin.h +++ b/php_suhosin.h @@ -250,7 +250,9 @@ ZEND_BEGIN_MODULE_GLOBALS(suhosin) zend_bool upload_disallow_elf; zend_bool upload_disallow_binary; zend_bool upload_remove_binary; +#ifdef SUHOSIN_EXPERIMENTAL zend_bool upload_allow_utf8; +#endif char *upload_verification_script; zend_bool no_more_variables; diff --git a/suhosin.c b/suhosin.c index fc84a94..8d25acc 100644 --- a/suhosin.c +++ b/suhosin.c @@ -824,7 +824,9 @@ PHP_INI_BEGIN() STD_PHP_INI_ENTRY("suhosin.upload.disallow_elf", "1", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_elf, zend_suhosin_globals, suhosin_globals) STD_PHP_INI_ENTRY("suhosin.upload.disallow_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_disallow_binary, zend_suhosin_globals, suhosin_globals) STD_PHP_INI_ENTRY("suhosin.upload.remove_binary", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_remove_binary, zend_suhosin_globals, suhosin_globals) - STD_PHP_INI_ENTRY("suhosin.upload.allow_utf8", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_allow_utf8, zend_suhosin_globals, suhosin_globals) +#ifdef SUHOSIN_EXPERIMENTAL + STD_PHP_INI_BOOLEAN("suhosin.upload.allow_utf8", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadBool, upload_allow_utf8, zend_suhosin_globals, suhosin_globals) +#endif STD_PHP_INI_ENTRY("suhosin.upload.verification_script", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateUploadString, upload_verification_script, zend_suhosin_globals, suhosin_globals) diff --git a/suhosin.ini b/suhosin.ini index 3ae8ff5..311bca7 100644 --- a/suhosin.ini +++ b/suhosin.ini @@ -105,9 +105,6 @@ ; | LOG_LOCAL7 | 31 | ; +--------------+-------+ ; -; Using constant names is only supported with the Suhosin-Patch. If in doubt, use -; the numeric value. -; ;suhosin.log.syslog.facility = LOG_USER ; @@ -141,9 +138,6 @@ ; |LOG_ERR | 7 | ; +------------+-------+ ; -; Using constant names is only supported with the Suhosin-Patch. If in doubt, use -; the numeric value. -; ;suhosin.log.syslog.priority = LOG_ALERT ; @@ -1325,8 +1319,8 @@ ; * Type: Boolean ; * Default: Off ; -; This option allows UTF-8 along with ASCII when using -; `suhosin.upload.disallow_binary` or `suhosin.upload.remove_binary`. +; This is an experimental feature. This option allows UTF-8 along with ASCII when +; using `suhosin.upload.disallow_binary` or `suhosin.upload.remove_binary`. ; ;suhosin.upload.allow_utf8 = Off ; diff --git a/tests/filter/suhosin_upload_disallow_binary_utf8.phpt b/tests/filter/suhosin_upload_disallow_binary_utf8.phpt index 557a8d5..b4627c7 100644 --- a/tests/filter/suhosin_upload_disallow_binary_utf8.phpt +++ b/tests/filter/suhosin_upload_disallow_binary_utf8.phpt @@ -11,7 +11,9 @@ suhosin.upload.allow_utf8=On max_file_uploads=40 suhosin.upload.max_uploads=40 --SKIPIF-- - + --COOKIE-- --GET-- --POST_RAW-- diff --git a/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt b/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt index 413d25a..0bf122b 100644 --- a/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt +++ b/tests/filter/suhosin_upload_disallow_binary_utf8fail.phpt @@ -11,7 +11,9 @@ suhosin.upload.allow_utf8=Off max_file_uploads=40 suhosin.upload.max_uploads=40 --SKIPIF-- - + --COOKIE-- --GET-- --POST_RAW-- diff --git a/tests/filter/suhosin_upload_remove_binary_utf8.phpt b/tests/filter/suhosin_upload_remove_binary_utf8.phpt index 6fbd240..1920dc5 100644 --- a/tests/filter/suhosin_upload_remove_binary_utf8.phpt +++ b/tests/filter/suhosin_upload_remove_binary_utf8.phpt @@ -12,7 +12,9 @@ suhosin.upload.allow_utf8=On max_file_uploads=40 suhosin.upload.max_uploads=40 --SKIPIF-- - + --COOKIE-- --GET-- --POST_RAW-- diff --git a/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt b/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt index 5c31115..56de404 100644 --- a/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt +++ b/tests/filter/suhosin_upload_remove_binary_utf8fail.phpt @@ -12,7 +12,9 @@ suhosin.upload.allow_utf8=Off max_file_uploads=40 suhosin.upload.max_uploads=40 --SKIPIF-- - + --COOKIE-- --GET-- --POST_RAW-- diff --git a/ufilter.c b/ufilter.c index 1669e88..f3c3054 100644 --- a/ufilter.c +++ b/ufilter.c @@ -149,19 +149,23 @@ return_failure: } /* }}} */ -static inline int suhosin_validate_utf8_multibyte(const char* cp) +#ifdef SUHOSIN_EXPERIMENTAL +static inline int suhosin_validate_utf8_multibyte(const char* cp, size_t maxlen) { + if (maxlen < 2 || !(*cp & 0x80)) { return 0; } if ((*cp & 0xe0) == 0xc0 && // 1st byte is 110xxxxx (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx (*cp & 0x1e)) { // overlong check 110[xxxx]x 10xxxxxx return 2; } + if (maxlen < 3) { return 0; } if ((*cp & 0xf0) == 0xe0 && // 1st byte is 1110xxxx (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx ((*cp & 0x0f) | (*(cp+1) & 0x20))) { // 1110[xxxx] 10[x]xxxxx 10xxxxxx return 3; } + if (maxlen < 4) { return 0; } if ((*cp & 0xf8) == 0xf0 && // 1st byte is 11110xxx (*(cp+1) & 0xc0) == 0x80 && // 2nd byte is 10xxxxxx (*(cp+2) & 0xc0) == 0x80 && // 3rd byte is 10xxxxxx @@ -171,6 +175,7 @@ static inline int suhosin_validate_utf8_multibyte(const char* cp) } return 0; } +#endif int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TSRMLS_DC) { @@ -236,14 +241,15 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS if (*cp >= 32 || isspace(*cp)) { continue; } +#ifdef SUHOSIN_EXPERIMENTAL if ((*cp & 0x80) && SUHOSIN_G(upload_allow_utf8)) { SDEBUG("checking char %x", *cp); - if ((n = suhosin_validate_utf8_multibyte(cp))) { // valid UTF8 multibyte character + if ((n = suhosin_validate_utf8_multibyte(cp, cpend-cp))) { // valid UTF8 multibyte character cp += n - 1; continue; } } - +#endif suhosin_log(S_FILES, "uploaded file contains binary data - file dropped"); if (!SUHOSIN_G(simulation)) { goto continue_with_failure; @@ -261,15 +267,17 @@ int suhosin_rfc1867_filter(unsigned int event, void *event_data, void **extra TS for (i=0, j=0; ilength; i++) { if (mefd->data[i] >= 32 || isspace(mefd->data[i])) { mefd->data[j++] = mefd->data[i]; - } else if (SUHOSIN_G(upload_allow_utf8) && mefd->data[i] & 0x80) { - n = suhosin_validate_utf8_multibyte(mefd->data + i); + } +#ifdef SUHOSIN_EXPERIMENTAL + else if (SUHOSIN_G(upload_allow_utf8) && mefd->data[i] & 0x80) { + n = suhosin_validate_utf8_multibyte(mefd->data + i, mefd->length - i); if (!n) { continue; } - while (n) { + while (n--) { mefd->data[j++] = mefd->data[i++]; - n--; } i--; } +#endif } mefd->data[j] = '\0'; -- cgit v1.3