diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 836ee8345affb..53af6eff1eda0 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -226,6 +226,7 @@ PHP_MINIT_FUNCTION(filter) REGISTER_LONG_CONSTANT("FILTER_FLAG_IPV6", FILTER_FLAG_IPV6, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_FLAG_NO_RES_RANGE", FILTER_FLAG_NO_RES_RANGE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_FLAG_NO_PRIV_RANGE", FILTER_FLAG_NO_PRIV_RANGE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("FILTER_FLAG_GLOBAL_RANGE", FILTER_FLAG_GLOBAL_RANGE, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("FILTER_FLAG_HOSTNAME", FILTER_FLAG_HOSTNAME, CONST_CS | CONST_PERSISTENT); diff --git a/ext/filter/filter_private.h b/ext/filter/filter_private.h index d0eb010dd4854..86f5257643817 100644 --- a/ext/filter/filter_private.h +++ b/ext/filter/filter_private.h @@ -19,8 +19,8 @@ #define FILTER_FLAG_NONE 0x0000 -#define FILTER_REQUIRE_ARRAY 0x1000000 -#define FILTER_REQUIRE_SCALAR 0x2000000 +#define FILTER_REQUIRE_ARRAY 0x10000000 +#define FILTER_REQUIRE_SCALAR 0x20000000 #define FILTER_FORCE_ARRAY 0x4000000 #define FILTER_NULL_ON_FAILURE 0x8000000 @@ -46,10 +46,11 @@ #define FILTER_FLAG_PATH_REQUIRED 0x040000 #define FILTER_FLAG_QUERY_REQUIRED 0x080000 -#define FILTER_FLAG_IPV4 0x100000 -#define FILTER_FLAG_IPV6 0x200000 -#define FILTER_FLAG_NO_RES_RANGE 0x400000 -#define FILTER_FLAG_NO_PRIV_RANGE 0x800000 +#define FILTER_FLAG_IPV4 0x0100000 +#define FILTER_FLAG_IPV6 0x0200000 +#define FILTER_FLAG_NO_RES_RANGE 0x0400000 +#define FILTER_FLAG_NO_PRIV_RANGE 0x0800000 +#define FILTER_FLAG_GLOBAL_RANGE 0x1000000 #define FILTER_FLAG_HOSTNAME 0x100000 diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c index 108e8e3259c78..3b12162290f6d 100644 --- a/ext/filter/logical_filters.c +++ b/ext/filter/logical_filters.c @@ -897,7 +897,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } /* Check flags */ - if (flags & FILTER_FLAG_NO_PRIV_RANGE) { + if (flags & FILTER_FLAG_NO_PRIV_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) { if ( (ip[0] == 10) || (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) || @@ -907,7 +907,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ } } - if (flags & FILTER_FLAG_NO_RES_RANGE) { + if (flags & FILTER_FLAG_NO_RES_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) { if ( (ip[0] == 0) || (ip[0] >= 240) || @@ -917,6 +917,20 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ RETURN_VALIDATION_FAILED } } + + if (flags & FILTER_FLAG_GLOBAL_RANGE) { + if ( + (ip[0] == 100 && ip[1] >= 64 && ip[1] <= 127 ) || + (ip[0] == 192 && ip[1] == 0 && ip[2] == 0 ) || + (ip[0] == 192 && ip[1] == 0 && ip[2] == 2 ) || + (ip[0] == 198 && ip[1] >= 18 && ip[1] <= 19 ) || + (ip[0] == 198 && ip[1] == 51 && ip[2] == 100 ) || + (ip[0] == 203 && ip[1] == 0 && ip[2] == 113 ) + ) { + RETURN_VALIDATION_FAILED + } + } + break; case FORMAT_IPV6: @@ -927,14 +941,14 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ RETURN_VALIDATION_FAILED } /* Check flags */ - if (flags & FILTER_FLAG_NO_PRIV_RANGE) { + if (flags & FILTER_FLAG_NO_PRIV_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) { if (ip[0] >= 0xfc00 && ip[0] <= 0xfdff) { RETURN_VALIDATION_FAILED } } - if (flags & FILTER_FLAG_NO_RES_RANGE) { + if (flags & FILTER_FLAG_NO_RES_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) { if ((ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 - && ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && (ip[7] == 0 || ip[7] == 1)) + && ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && (ip[7] == 0 || ip[7] == 1)) || (ip[0] == 0x5f) || (ip[0] >= 0xfe80 && ip[0] <= 0xfebf) || (ip[0] == 0x2001 && (ip[1] == 0x0db8 || (ip[1] >= 0x0010 && ip[1] <= 0x001f))) @@ -942,8 +956,18 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ ) { RETURN_VALIDATION_FAILED } - } - } + } + if (flags & FILTER_FLAG_GLOBAL_RANGE) { + if ((ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 && ip[4] == 0 && ip[5] == 0xffff) || + (ip[0] == 0x0100 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0) || + (ip[0] == 0x2001 && ip[1] <= 0x01ff) || + (ip[0] == 0x2001 && ip[1] == 0x0002 && ip[2] == 0) || + (ip[0] >= 0xfc00 && ip[0] <= 0xfdff) + ) { + RETURN_VALIDATION_FAILED + } + } + } break; } } diff --git a/ext/filter/tests/bug77221.phpt b/ext/filter/tests/bug77221.phpt new file mode 100644 index 0000000000000..307a83898ac44 --- /dev/null +++ b/ext/filter/tests/bug77221.phpt @@ -0,0 +1,121 @@ +--TEST-- +Bug #77221 (Request IP address filter flag to exclude non-global IP addresses) +--SKIPIF-- + +--FILE-- + $range) { + list($min, $max) = $range; + var_dump($key); + var_dump(filter_var($min, FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE)); + var_dump(filter_var($max, FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE)); +} + +var_dump(filter_var('185.85.0.29', FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE)); +var_dump(filter_var('64:ff9b::', FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE)); +var_dump(filter_var('64:ff9b::ffff', FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE)); + +?> +--EXPECT-- +string(9) "0.0.0.0/8" +bool(false) +bool(false) +string(10) "10.0.0.0/8" +bool(false) +bool(false) +string(13) "100.64.0.0/10" +bool(false) +bool(false) +string(11) "127.0.0.0/8" +bool(false) +bool(false) +string(14) "169.254.0.0/16" +bool(false) +bool(false) +string(13) "172.16.0.0/12" +bool(false) +bool(false) +string(12) "192.0.0.0/24" +bool(false) +bool(false) +string(12) "192.0.2.0/24" +bool(false) +bool(false) +string(14) "192.168.0.0/16" +bool(false) +bool(false) +string(13) "198.18.0.0/15" +bool(false) +bool(false) +string(15) "198.51.100.0/24" +bool(false) +bool(false) +string(14) "203.0.113.0/24" +bool(false) +bool(false) +string(11) "240.0.0.0/4" +bool(false) +bool(false) +string(6) "::/128" +bool(false) +bool(false) +string(7) "::1/128" +bool(false) +bool(false) +string(13) "::ffff:0:0/96" +bool(false) +bool(false) +string(8) "100::/64" +bool(false) +bool(false) +string(9) "2001::/23" +bool(false) +bool(false) +string(11) "2001:2::/48" +bool(false) +bool(false) +string(13) "2001:db8::/32" +bool(false) +bool(false) +string(12) "2001:10::/28" +bool(false) +bool(false) +string(8) "fc00::/7" +bool(false) +bool(false) +string(9) "fe80::/10" +bool(false) +bool(false) +string(11) "185.85.0.29" +string(9) "64:ff9b::" +string(13) "64:ff9b::ffff"