summaryrefslogtreecommitdiff
path: root/ext/filter
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2010-10-21 08:52:46 +0200
committerOndřej Surý <ondrej@sury.org>2010-10-21 08:52:46 +0200
commit01fcdff3849c3691d9aaeaab735846ab6d8895ca (patch)
tree6460876d356113fa7053df36f2aa00baa7db24a9 /ext/filter
parent855a09f4eded707941180c9d90acd17c25e29447 (diff)
downloadphp-01fcdff3849c3691d9aaeaab735846ab6d8895ca.tar.gz
Imported Upstream version 5.3.3upstream/5.3.3
Diffstat (limited to 'ext/filter')
-rw-r--r--ext/filter/filter.c18
-rw-r--r--ext/filter/filter_private.h5
-rw-r--r--ext/filter/logical_filters.c57
-rw-r--r--ext/filter/php_filter.h4
-rw-r--r--ext/filter/sanitizing_filters.c22
-rw-r--r--ext/filter/tests/008.phpt16
-rw-r--r--ext/filter/tests/016.phpt6
-rw-r--r--ext/filter/tests/033.phpt2
-rwxr-xr-xext/filter/tests/046.phpt50
-rw-r--r--ext/filter/tests/bug51192.phpt13
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&#39;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&#60;&#62;() O&#39;Henry 하퍼
+full_special_chars PHP 1 foo@bar.com http://a.b.c 1.2.3.4 123 123abc&lt;&gt;() O&#039;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)