Skip to content

Commit d8fc05c

Browse files
vnsavagebukka
authored andcommittedJul 18, 2022
Add FILTER_FLAG_GLOBAL_RANGE to filter Global IPs as per RFC 6890
1 parent ffdf25a commit d8fc05c

File tree

7 files changed

+170
-12
lines changed

7 files changed

+170
-12
lines changed
 

‎NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ PHP NEWS
2020
- COM:
2121
. Fixed bug GH-8750 (Can not create VT_ERROR variant type). (cmb)
2222

23+
- Filter:
24+
. Added FILTER_FLAG_GLOBAL_RANGE to filter Global IPs. (vnsavage)
25+
2326
- FPM:
2427
. Added listen.setfib pool option to set route FIB on FreeBSD. (David Carlier)
2528
. Added access.suppress_path pool option to filter access log entries.

‎UPGRADING

+3
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,9 @@ PHP 8.2 UPGRADE NOTES
349349
. CURL_VERSION_UNICODE (libcurl >= 7.72.0)
350350
. CURL_VERSION_ZSTD (libcurl >= 7.72.0)
351351

352+
- Filter
353+
. FILTER_FLAG_GLOBAL_RANGE
354+
352355
- Sockets:
353356
. SO_INCOMING_CPU
354357
. SO_MEMINFO

‎ext/filter/filter.stub.php

+5
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,11 @@
276276
* @cname FILTER_FLAG_NO_PRIV_RANGE
277277
*/
278278
const FILTER_FLAG_NO_PRIV_RANGE = UNKNOWN;
279+
/**
280+
* @var int
281+
* @cname FILTER_FLAG_GLOBAL_RANGE
282+
*/
283+
const FILTER_FLAG_GLOBAL_RANGE = UNKNOWN;
279284

280285
/**
281286
* @var int

‎ext/filter/filter_arginfo.h

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎ext/filter/filter_private.h

+5-4
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@
4646
#define FILTER_FLAG_PATH_REQUIRED 0x040000
4747
#define FILTER_FLAG_QUERY_REQUIRED 0x080000
4848

49-
#define FILTER_FLAG_IPV4 0x100000
50-
#define FILTER_FLAG_IPV6 0x200000
51-
#define FILTER_FLAG_NO_RES_RANGE 0x400000
52-
#define FILTER_FLAG_NO_PRIV_RANGE 0x800000
49+
#define FILTER_FLAG_IPV4 0x00100000
50+
#define FILTER_FLAG_IPV6 0x00200000
51+
#define FILTER_FLAG_NO_RES_RANGE 0x00400000
52+
#define FILTER_FLAG_NO_PRIV_RANGE 0x00800000
53+
#define FILTER_FLAG_GLOBAL_RANGE 0x10000000
5354

5455
#define FILTER_FLAG_HOSTNAME 0x100000
5556

‎ext/filter/logical_filters.c

+31-7
Original file line numberDiff line numberDiff line change
@@ -897,7 +897,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
897897
}
898898

899899
/* Check flags */
900-
if (flags & FILTER_FLAG_NO_PRIV_RANGE) {
900+
if (flags & FILTER_FLAG_NO_PRIV_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) {
901901
if (
902902
(ip[0] == 10) ||
903903
(ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) ||
@@ -907,7 +907,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
907907
}
908908
}
909909

910-
if (flags & FILTER_FLAG_NO_RES_RANGE) {
910+
if (flags & FILTER_FLAG_NO_RES_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) {
911911
if (
912912
(ip[0] == 0) ||
913913
(ip[0] >= 240) ||
@@ -917,6 +917,20 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
917917
RETURN_VALIDATION_FAILED
918918
}
919919
}
920+
921+
if (flags & FILTER_FLAG_GLOBAL_RANGE) {
922+
if (
923+
(ip[0] == 100 && ip[1] >= 64 && ip[1] <= 127 ) ||
924+
(ip[0] == 192 && ip[1] == 0 && ip[2] == 0 ) ||
925+
(ip[0] == 192 && ip[1] == 0 && ip[2] == 2 ) ||
926+
(ip[0] == 198 && ip[1] >= 18 && ip[1] <= 19 ) ||
927+
(ip[0] == 198 && ip[1] == 51 && ip[2] == 100 ) ||
928+
(ip[0] == 203 && ip[1] == 0 && ip[2] == 113 )
929+
) {
930+
RETURN_VALIDATION_FAILED
931+
}
932+
}
933+
920934
break;
921935

922936
case FORMAT_IPV6:
@@ -927,23 +941,33 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
927941
RETURN_VALIDATION_FAILED
928942
}
929943
/* Check flags */
930-
if (flags & FILTER_FLAG_NO_PRIV_RANGE) {
944+
if (flags & FILTER_FLAG_NO_PRIV_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) {
931945
if (ip[0] >= 0xfc00 && ip[0] <= 0xfdff) {
932946
RETURN_VALIDATION_FAILED
933947
}
934948
}
935-
if (flags & FILTER_FLAG_NO_RES_RANGE) {
949+
if (flags & FILTER_FLAG_NO_RES_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) {
936950
if ((ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0
937-
&& ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && (ip[7] == 0 || ip[7] == 1))
951+
&& ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && (ip[7] == 0 || ip[7] == 1))
938952
|| (ip[0] == 0x5f)
939953
|| (ip[0] >= 0xfe80 && ip[0] <= 0xfebf)
940954
|| (ip[0] == 0x2001 && (ip[1] == 0x0db8 || (ip[1] >= 0x0010 && ip[1] <= 0x001f)))
941955
|| (ip[0] == 0x3ff3)
942956
) {
943957
RETURN_VALIDATION_FAILED
944958
}
945-
}
946-
}
959+
}
960+
if (flags & FILTER_FLAG_GLOBAL_RANGE) {
961+
if ((ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 && ip[4] == 0 && ip[5] == 0xffff) ||
962+
(ip[0] == 0x0100 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0) ||
963+
(ip[0] == 0x2001 && ip[1] <= 0x01ff) ||
964+
(ip[0] == 0x2001 && ip[1] == 0x0002 && ip[2] == 0) ||
965+
(ip[0] >= 0xfc00 && ip[0] <= 0xfdff)
966+
) {
967+
RETURN_VALIDATION_FAILED
968+
}
969+
}
970+
}
947971
break;
948972
}
949973
}

‎ext/filter/tests/bug77221.phpt

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
--TEST--
2+
Bug #77221 (Request IP address filter flag to exclude non-global IP addresses)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('filter')) die("skip filter extension not available");
6+
?>
7+
--FILE--
8+
<?php
9+
10+
$non_global_ranges = [];
11+
$non_global_ranges['0.0.0.0/8'] = ['0.0.0.0', '0.255.255.255'];
12+
$non_global_ranges['10.0.0.0/8'] = ['10.0.0.0', '10.255.255.255'];
13+
$non_global_ranges['100.64.0.0/10'] = ['100.64.0.0', '100.127.255.255'];
14+
$non_global_ranges['127.0.0.0/8'] = ['127.0.0.0', '127.255.255.255'];
15+
$non_global_ranges['169.254.0.0/16'] = ['169.254.0.0', '169.254.255.255'];
16+
$non_global_ranges['172.16.0.0/12'] = ['172.16.0.0', '172.31.255.255'];
17+
$non_global_ranges['192.0.0.0/24'] = ['192.0.0.0', '192.0.0.255'];
18+
$non_global_ranges['192.0.2.0/24'] = ['192.0.2.0', '192.0.2.255'];
19+
$non_global_ranges['192.168.0.0/16'] = ['192.168.0.0', '192.168.255.255'];
20+
$non_global_ranges['198.18.0.0/15'] = ['198.18.0.0', '198.19.255.255'];
21+
$non_global_ranges['198.51.100.0/24'] = ['198.51.100.0', '198.51.100.255'];
22+
$non_global_ranges['203.0.113.0/24'] = ['203.0.113.0', '203.0.113.255'];
23+
$non_global_ranges['240.0.0.0/4'] = ['240.0.0.0', '255.255.255.255'];
24+
25+
$non_global_ranges['::/128'] = ['::0', '::'];
26+
$non_global_ranges['::1/128'] = ['0000:0000:0000:0000:0000:0000:0000:1', '0:0:0:0:0:0:0:1'];
27+
$non_global_ranges['::ffff:0:0/96'] = ['::ffff:0:0', '::ffff:ffff:ffff'];
28+
$non_global_ranges['100::/64'] = ['0100::', '100::ffff:ffff:ffff:ffff'];
29+
$non_global_ranges['2001::/23'] = ['2001::', '2001:01ff:ffff:ffff:ffff:ffff:ffff:ffff'];
30+
$non_global_ranges['2001:2::/48'] = ['2001:2::', '2001:2:0:ffff:ffff:ffff:ffff:ffff'];
31+
$non_global_ranges['2001:db8::/32'] = ['2001:db8::', '2001:db8:ffff:ffff:ffff:ffff:ffff:ffff'];
32+
$non_global_ranges['2001:10::/28'] = ['2001:10::', '2001:1f:ffff:ffff:ffff:ffff:ffff:ffff'];
33+
$non_global_ranges['fc00::/7'] = ['fc00::', 'fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'];
34+
$non_global_ranges['fe80::/10'] = ['fe80::', 'febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff'];
35+
36+
37+
foreach ($non_global_ranges as $key => $range) {
38+
list($min, $max) = $range;
39+
var_dump($key);
40+
var_dump(filter_var($min, FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE));
41+
var_dump(filter_var($max, FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE));
42+
}
43+
44+
var_dump(filter_var('185.85.0.29', FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE));
45+
var_dump(filter_var('64:ff9b::', FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE));
46+
var_dump(filter_var('64:ff9b::ffff', FILTER_VALIDATE_IP, FILTER_FLAG_GLOBAL_RANGE));
47+
48+
?>
49+
--EXPECT--
50+
string(9) "0.0.0.0/8"
51+
bool(false)
52+
bool(false)
53+
string(10) "10.0.0.0/8"
54+
bool(false)
55+
bool(false)
56+
string(13) "100.64.0.0/10"
57+
bool(false)
58+
bool(false)
59+
string(11) "127.0.0.0/8"
60+
bool(false)
61+
bool(false)
62+
string(14) "169.254.0.0/16"
63+
bool(false)
64+
bool(false)
65+
string(13) "172.16.0.0/12"
66+
bool(false)
67+
bool(false)
68+
string(12) "192.0.0.0/24"
69+
bool(false)
70+
bool(false)
71+
string(12) "192.0.2.0/24"
72+
bool(false)
73+
bool(false)
74+
string(14) "192.168.0.0/16"
75+
bool(false)
76+
bool(false)
77+
string(13) "198.18.0.0/15"
78+
bool(false)
79+
bool(false)
80+
string(15) "198.51.100.0/24"
81+
bool(false)
82+
bool(false)
83+
string(14) "203.0.113.0/24"
84+
bool(false)
85+
bool(false)
86+
string(11) "240.0.0.0/4"
87+
bool(false)
88+
bool(false)
89+
string(6) "::/128"
90+
bool(false)
91+
bool(false)
92+
string(7) "::1/128"
93+
bool(false)
94+
bool(false)
95+
string(13) "::ffff:0:0/96"
96+
bool(false)
97+
bool(false)
98+
string(8) "100::/64"
99+
bool(false)
100+
bool(false)
101+
string(9) "2001::/23"
102+
bool(false)
103+
bool(false)
104+
string(11) "2001:2::/48"
105+
bool(false)
106+
bool(false)
107+
string(13) "2001:db8::/32"
108+
bool(false)
109+
bool(false)
110+
string(12) "2001:10::/28"
111+
bool(false)
112+
bool(false)
113+
string(8) "fc00::/7"
114+
bool(false)
115+
bool(false)
116+
string(9) "fe80::/10"
117+
bool(false)
118+
bool(false)
119+
string(11) "185.85.0.29"
120+
string(9) "64:ff9b::"
121+
string(13) "64:ff9b::ffff"

0 commit comments

Comments
 (0)