diff options
author | Ondřej Surý <ondrej@sury.org> | 2010-10-21 08:52:46 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2010-10-21 08:52:46 +0200 |
commit | 01fcdff3849c3691d9aaeaab735846ab6d8895ca (patch) | |
tree | 6460876d356113fa7053df36f2aa00baa7db24a9 /ext/filter | |
parent | 855a09f4eded707941180c9d90acd17c25e29447 (diff) | |
download | php-01fcdff3849c3691d9aaeaab735846ab6d8895ca.tar.gz |
Imported Upstream version 5.3.3upstream/5.3.3
Diffstat (limited to 'ext/filter')
-rw-r--r-- | ext/filter/filter.c | 18 | ||||
-rw-r--r-- | ext/filter/filter_private.h | 5 | ||||
-rw-r--r-- | ext/filter/logical_filters.c | 57 | ||||
-rw-r--r-- | ext/filter/php_filter.h | 4 | ||||
-rw-r--r-- | ext/filter/sanitizing_filters.c | 22 | ||||
-rw-r--r-- | ext/filter/tests/008.phpt | 16 | ||||
-rw-r--r-- | ext/filter/tests/016.phpt | 6 | ||||
-rw-r--r-- | ext/filter/tests/033.phpt | 2 | ||||
-rwxr-xr-x | ext/filter/tests/046.phpt | 50 | ||||
-rw-r--r-- | ext/filter/tests/bug51192.phpt | 13 |
10 files changed, 152 insertions, 41 deletions
diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 087ca2f98..02373e8d4 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -19,7 +19,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: filter.c 294106 2010-01-27 17:22:54Z johannes $ */ +/* $Id: filter.c 298196 2010-04-20 04:31:11Z aharvey $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -52,6 +52,7 @@ static const filter_list_entry filter_list[] = { { "stripped", FILTER_SANITIZE_STRING, php_filter_string }, { "encoded", FILTER_SANITIZE_ENCODED, php_filter_encoded }, { "special_chars", FILTER_SANITIZE_SPECIAL_CHARS, php_filter_special_chars }, + { "full_special_chars", FILTER_SANITIZE_FULL_SPECIAL_CHARS, php_filter_full_special_chars }, { "unsafe_raw", FILTER_UNSAFE_RAW, php_filter_unsafe_raw }, { "email", FILTER_SANITIZE_EMAIL, php_filter_email }, { "url", FILTER_SANITIZE_URL, php_filter_url }, @@ -238,6 +239,7 @@ PHP_MINIT_FUNCTION(filter) REGISTER_LONG_CONSTANT("FILTER_SANITIZE_STRIPPED", FILTER_SANITIZE_STRING, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_SANITIZE_ENCODED", FILTER_SANITIZE_ENCODED, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_SANITIZE_SPECIAL_CHARS", FILTER_SANITIZE_SPECIAL_CHARS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("FILTER_SANITIZE_FULL_SPECIAL_CHARS", FILTER_SANITIZE_SPECIAL_CHARS, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_SANITIZE_EMAIL", FILTER_SANITIZE_EMAIL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_SANITIZE_URL", FILTER_SANITIZE_URL, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_SANITIZE_NUMBER_INT", FILTER_SANITIZE_NUMBER_INT, CONST_CS | CONST_PERSISTENT); @@ -314,7 +316,7 @@ PHP_MINFO_FUNCTION(filter) { php_info_print_table_start(); php_info_print_table_row( 2, "Input Validation and Filtering", "enabled" ); - php_info_print_table_row( 2, "Revision", "$Revision: 294106 $"); + php_info_print_table_row( 2, "Revision", "$Revision: 298196 $"); php_info_print_table_end(); DISPLAY_INI_ENTRIES(); @@ -778,6 +780,12 @@ PHP_FUNCTION(filter_input) return; } } + + /* The FILTER_NULL_ON_FAILURE flag inverts the usual return values of + * the function: normally when validation fails false is returned, and + * when the input value doesn't exist NULL is returned. With the flag + * set, NULL and false should be returned, respectively. Ergo, although + * the code below looks incorrect, it's actually right. */ if (filter_flags & FILTER_NULL_ON_FAILURE) { RETURN_FALSE; } else { @@ -844,6 +852,12 @@ PHP_FUNCTION(filter_input_array) PHP_FILTER_GET_LONG_OPT(option, filter_flags); } } + + /* The FILTER_NULL_ON_FAILURE flag inverts the usual return values of + * the function: normally when validation fails false is returned, and + * when the input value doesn't exist NULL is returned. With the flag + * set, NULL and false should be returned, respectively. Ergo, although + * the code below looks incorrect, it's actually right. */ if (filter_flags & FILTER_NULL_ON_FAILURE) { RETURN_FALSE; } else { diff --git a/ext/filter/filter_private.h b/ext/filter/filter_private.h index 892087757..7cb6ca3ce 100644 --- a/ext/filter/filter_private.h +++ b/ext/filter/filter_private.h @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: filter_private.h 293036 2010-01-03 09:23:27Z sebastian $ */ +/* $Id: filter_private.h 297245 2010-03-31 22:59:09Z rasmus $ */ #ifndef FILTER_PRIVATE_H #define FILTER_PRIVATE_H @@ -78,7 +78,8 @@ #define FILTER_SANITIZE_NUMBER_INT 0x0207 #define FILTER_SANITIZE_NUMBER_FLOAT 0x0208 #define FILTER_SANITIZE_MAGIC_QUOTES 0x0209 -#define FILTER_SANITIZE_LAST 0x0209 +#define FILTER_SANITIZE_FULL_SPECIAL_CHARS 0x020a +#define FILTER_SANITIZE_LAST 0x020a #define FILTER_SANITIZE_ALL 0x0200 diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index f8f453e41..c6eebac36 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: logical_filters.c 293996 2010-01-25 16:14:28Z johannes $ */ +/* $Id: logical_filters.c 297353 2010-04-02 18:27:48Z rasmus $ */ #include "php_filter.h" #include "filter_private.h" @@ -68,7 +68,7 @@ static int php_filter_parse_int(const char *str, unsigned int str_len, long *ret TSRMLS_DC) { /* {{{ */ long ctx_value; - int sign = 0; + int sign = 0, digit = 0; const char *end = str + str_len; switch (*str) { @@ -82,7 +82,7 @@ static int php_filter_parse_int(const char *str, unsigned int str_len, long *ret /* must start with 1..9*/ if (str < end && *str >= '1' && *str <= '9') { - ctx_value = ((*(str++)) - '0'); + ctx_value = ((sign)?-1:1) * ((*(str++)) - '0'); } else { return -1; } @@ -95,19 +95,18 @@ static int php_filter_parse_int(const char *str, unsigned int str_len, long *ret while (str < end) { if (*str >= '0' && *str <= '9') { - ctx_value = (ctx_value * 10) + (*(str++) - '0'); + digit = (*(str++) - '0'); + if ( (!sign) && ctx_value <= (LONG_MAX-digit)/10 ) { + ctx_value = (ctx_value * 10) + digit; + } else if ( sign && ctx_value >= (LONG_MIN+digit)/10) { + ctx_value = (ctx_value * 10) - digit; + } else { + return -1; + } } else { return -1; } } - if (sign) { - ctx_value = -ctx_value; - if (ctx_value > 0) { /* overflow */ - return -1; - } - } else if (ctx_value < 0) { /* overflow */ - return -1; - } *ret = ctx_value; return 1; @@ -466,8 +465,13 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ e = url->host + strlen(url->host); s = url->host; + /* First char of hostname must be alphanumeric */ + if(!isalnum((int)*(unsigned char *)s)) { + goto bad_url; + } + while (s < e) { - if (!isalnum((int)*(unsigned char *)s) && *s != '_' && *s != '.') { + if (!isalnum((int)*(unsigned char *)s) && *s != '-' && *s != '.') { goto bad_url; } s++; @@ -494,8 +498,31 @@ bad_url: void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ { - /* From http://cvs.php.net/co.php/pear/HTML_QuickForm/QuickForm/Rule/Email.php?r=1.4 */ - const char regexp[] = "/^((\\\"[^\\\"\\f\\n\\r\\t\\b]+\\\")|([A-Za-z0-9_][A-Za-z0-9_\\!\\#\\$\\%\\&\\'\\*\\+\\-\\~\\/\\=\\?\\^\\`\\|\\{\\}]*(\\.[A-Za-z0-9_\\!\\#\\$\\%\\&\\'\\*\\+\\-\\~\\/\\=\\?\\^\\`\\|\\{\\}]*)*))@((\\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9])(([A-Za-z0-9\\-])*([A-Za-z0-9]))?(\\.(?=[A-Za-z0-9\\-]))?)+[A-Za-z]+))$/D"; + /* + * The regex below is based on a regex by Michael Rushton. + * However, it is not identical. I changed it to only consider routeable + * addresses as valid. Michael's regex considers a@b a valid address + * which conflicts with section 2.3.5 of RFC 5321 which states that: + * + * Only resolvable, fully-qualified domain names (FQDNs) are permitted + * when domain names are used in SMTP. In other words, names that can + * be resolved to MX RRs or address (i.e., A or AAAA) RRs (as discussed + * in Section 5) are permitted, as are CNAME RRs whose targets can be + * resolved, in turn, to MX or address RRs. Local nicknames or + * unqualified names MUST NOT be used. + * + * This regex does not handle comments and folding whitespace. While + * this is technically valid in an email address, these parts aren't + * actually part of the address itself. + * + * Michael's regex carries this copyright: + * + * Copyright © Michael Rushton 2009-10 + * http://squiloople.com/ + * Feel free to use and redistribute this code. But please keep this copyright notice. + * + */ + const char regexp[] = "/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD"; pcre *re = NULL; pcre_extra *pcre_extra = NULL; diff --git a/ext/filter/php_filter.h b/ext/filter/php_filter.h index 1c5d84628..1cbf5c159 100644 --- a/ext/filter/php_filter.h +++ b/ext/filter/php_filter.h @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_filter.h 293036 2010-01-03 09:23:27Z sebastian $ */ +/* $Id: php_filter.h 297245 2010-03-31 22:59:09Z rasmus $ */ #ifndef PHP_FILTER_H #define PHP_FILTER_H @@ -28,6 +28,7 @@ #include "php_ini.h" #include "ext/standard/info.h" #include "ext/standard/php_string.h" +#include "ext/standard/html.h" #include "php_variables.h" extern zend_module_entry filter_module_entry; @@ -81,6 +82,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL); void php_filter_string(PHP_INPUT_FILTER_PARAM_DECL); void php_filter_encoded(PHP_INPUT_FILTER_PARAM_DECL); void php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL); +void php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL); void php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL); void php_filter_email(PHP_INPUT_FILTER_PARAM_DECL); void php_filter_url(PHP_INPUT_FILTER_PARAM_DECL); diff --git a/ext/filter/sanitizing_filters.c b/ext/filter/sanitizing_filters.c index c5152dbe1..08116f596 100644 --- a/ext/filter/sanitizing_filters.c +++ b/ext/filter/sanitizing_filters.c @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: sanitizing_filters.c 293036 2010-01-03 09:23:27Z sebastian $ */ +/* $Id: sanitizing_filters.c 297245 2010-03-31 22:59:09Z rasmus $ */ #include "php_filter.h" #include "filter_private.h" @@ -242,6 +242,24 @@ void php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL) } /* }}} */ +/* {{{ php_filter_full_special_chars */ +void php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL) +{ + char *buf; + int len, quotes; + + if (!(flags & FILTER_FLAG_NO_ENCODE_QUOTES)) { + quotes = ENT_QUOTES; + } else { + quotes = ENT_NOQUOTES; + } + buf = php_escape_html_entities_ex(Z_STRVAL_P(value), Z_STRLEN_P(value), &len, 1, quotes, SG(default_charset), 0 TSRMLS_CC); + efree(Z_STRVAL_P(value)); + Z_STRVAL_P(value) = buf; + Z_STRLEN_P(value) = len; +} +/* }}} */ + /* {{{ php_filter_unsafe_raw */ void php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL) { @@ -266,6 +284,8 @@ void php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL) } /* }}} */ + + /* {{{ php_filter_email */ #define SAFE "$-_.+" #define EXTRA "!*'()," diff --git a/ext/filter/tests/008.phpt b/ext/filter/tests/008.phpt index 7ba42fa73..8a4340542 100644 --- a/ext/filter/tests/008.phpt +++ b/ext/filter/tests/008.phpt @@ -11,7 +11,7 @@ var_dump(filter_list(array())); echo "Done\n"; ?> --EXPECTF-- -array(18) { +array(19) { [0]=> string(3) "int" [1]=> @@ -35,18 +35,20 @@ array(18) { [10]=> string(13) "special_chars" [11]=> - string(10) "unsafe_raw" + string(18) "full_special_chars" [12]=> - string(5) "email" + string(10) "unsafe_raw" [13]=> - string(3) "url" + string(5) "email" [14]=> - string(10) "number_int" + string(3) "url" [15]=> - string(12) "number_float" + string(10) "number_int" [16]=> - string(12) "magic_quotes" + string(12) "number_float" [17]=> + string(12) "magic_quotes" + [18]=> string(8) "callback" } diff --git a/ext/filter/tests/016.phpt b/ext/filter/tests/016.phpt index fbe8f3b3f..c6783444d 100644 --- a/ext/filter/tests/016.phpt +++ b/ext/filter/tests/016.phpt @@ -33,13 +33,13 @@ string(17) "abuse@example.com" bool(false) bool(false) bool(false) -string(8) "test@com" +bool(false) bool(false) bool(false) string(57) "QWERTYUIOPASDFGHJKLZXCVBNM@QWERTYUIOPASDFGHJKLZXCVBNM.NET" -string(26) "e.x.a.m.p.l.e.@example.com" -string(42) "firstname.lastname@employee.2something.com" bool(false) +string(42) "firstname.lastname@employee.2something.com" +string(9) "-@foo.com" bool(false) bool(false) bool(false) diff --git a/ext/filter/tests/033.phpt b/ext/filter/tests/033.phpt index 143d0c10e..04daa6133 100644 --- a/ext/filter/tests/033.phpt +++ b/ext/filter/tests/033.phpt @@ -4,6 +4,7 @@ Test all filters returned by filter_list() <?php if (!extension_loaded("filter")) die("skip"); ?> --INI-- precision=14 +default_charset=UTF-8 --FILE-- <?php include dirname(__FILE__) . '/033_run.inc'; @@ -20,6 +21,7 @@ string PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 12 stripped PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc() O'Henry 하퍼 encoded PHP 1 foo%40bar.com http%3A%2F%2Fa.b.c 1.2.3.4 123 123abc%3C%3E%28%29 O%27Henry %ED%95%98%ED%8D%BC special_chars PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc<>() O'Henry 하퍼 +full_special_chars PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc<>() O'Henry 하퍼 unsafe_raw PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc<>() O'Henry 하퍼 email PHP 1 foo@bar.com httpa.b.c 1.2.3.4 123 123abc O'Henry url PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc<>() O'Henry diff --git a/ext/filter/tests/046.phpt b/ext/filter/tests/046.phpt index 813328946..bc454420a 100755 --- a/ext/filter/tests/046.phpt +++ b/ext/filter/tests/046.phpt @@ -4,16 +4,46 @@ Integer overflow <?php if (!extension_loaded("filter")) die("skip"); ?> --FILE-- <?php -$s = sprintf("%d", PHP_INT_MAX); -var_dump(is_long(filter_var($s, FILTER_VALIDATE_INT))); +$max = sprintf("%d", PHP_INT_MAX); +switch($max) { +case "2147483647": /* 32-bit systems */ + $min = "-2147483648"; + $overflow = "2147483648"; + $underflow = "-2147483649"; + break; +case "9223372036854775807": /* 64-bit systems */ + $min = "-9223372036854775808"; + $overflow = "9223372036854775808"; + $underflow = "-9223372036854775809"; + break; +default: + die("failed: unknown value for PHP_MAX_INT"); + break; +} -$s = sprintf("%.0f", PHP_INT_MAX+1); -var_dump(filter_var($s, FILTER_VALIDATE_INT)); +function test_validation($val, $msg) { + $f = filter_var($val, FILTER_VALIDATE_INT); + echo "$msg filtered: "; var_dump($f); // filtered value (or false) + echo "$msg is_long: "; var_dump(is_long($f)); // test validation + echo "$msg equal: "; var_dump($val == $f); // test equality of result +} -$s = sprintf("%d", -PHP_INT_MAX); -var_dump(is_long(filter_var($s, FILTER_VALIDATE_INT))); +// PHP_INT_MAX +test_validation($max, "max"); +test_validation($overflow, "overflow"); +test_validation($min, "min"); +test_validation($underflow, "underflow"); ?> ---EXPECT-- -bool(true) -bool(false) -bool(true) +--EXPECTF-- +max filtered: int(%d) +max is_long: bool(true) +max equal: bool(true) +overflow filtered: bool(false) +overflow is_long: bool(false) +overflow equal: bool(false) +min filtered: int(-%d) +min is_long: bool(true) +min equal: bool(true) +underflow filtered: bool(false) +underflow is_long: bool(false) +underflow equal: bool(false) diff --git a/ext/filter/tests/bug51192.phpt b/ext/filter/tests/bug51192.phpt new file mode 100644 index 000000000..96c67eae1 --- /dev/null +++ b/ext/filter/tests/bug51192.phpt @@ -0,0 +1,13 @@ +--TEST-- +bug 51192, FILTER_VALIDATE_URL will invalidate a hostname that includes '-' +--SKIPIF-- +<?php if (!extension_loaded("filter")) die("skip"); ?> +--FILE-- +<?php +var_dump(filter_var('http://example.com/path', FILTER_VALIDATE_URL)); +var_dump(filter_var('http://exa-mple.com/path', FILTER_VALIDATE_URL)); +var_dump(filter_var('http://exa_mple.com/path', FILTER_VALIDATE_URL)); +--EXPECT-- +string(23) "http://example.com/path" +string(24) "http://exa-mple.com/path" +bool(false) |