Skip to content

Commit c5469fa

Browse files
committed
Merge branch 'PHP-8.3' into PHP-8.4
2 parents 5f13c62 + 1d36d3b commit c5469fa

17 files changed

+162
-106
lines changed

ext/filter/logical_filters.c

Lines changed: 136 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -869,15 +869,120 @@ static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8])
869869
}
870870
/* }}} */
871871

872-
void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
872+
/* From the tables in RFC 6890 - Special-Purpose IP Address Registriesi
873+
* Including errata: https://www.rfc-editor.org/errata_search.php?rfc=6890&rec_status=1 */
874+
static bool ipv4_get_status_flags(const int ip[8], bool *global, bool *reserved, bool *private)
875+
{
876+
*global = false;
877+
*reserved = false;
878+
*private = false;
879+
880+
if (ip[0] == 0) {
881+
/* RFC 0791 - This network */
882+
*reserved = true;
883+
} else if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0) {
884+
/* RFC 1122 - This host on this network */
885+
*reserved = true;
886+
} else if (ip[0] == 10) {
887+
/* RFC 1918 - Private Use */
888+
*private = true;
889+
} else if (ip[0] == 100 && ip[1] >= 64 && ip[1] <= 127) {
890+
/* RFC 6598 - Shared Address Space */
891+
} else if (ip[0] == 127) {
892+
/* RFC 1122 - Loopback */
893+
*reserved = true;
894+
} else if (ip[0] == 169 && ip[1] == 254) {
895+
/* RFC 3927 - Link Local */
896+
*reserved = true;
897+
} else if (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) {
898+
/* RFC 1918 - Private Use */
899+
*private = true;
900+
} else if (ip[0] == 192 && ip[1] == 0 && ip[2] == 0) {
901+
/* RFC 6890 - IETF Protocol Assignments */
902+
} else if (ip[0] == 192 && ip[1] == 0 && ip[2] == 0 && ip[3] >= 0 && ip[3] <= 7) {
903+
/* RFC 6333 - DS-Lite */
904+
} else if (ip[0] == 192 && ip[1] == 0 && ip[2] == 2) {
905+
/* RFC 5737 - Documentation */
906+
} else if (ip[0] == 192 && ip[1] == 88 && ip[2] == 99) {
907+
/* RFC 3068 - 6to4 Relay Anycast */
908+
*global = true;
909+
} else if (ip[0] == 192 && ip[1] == 168) {
910+
/* RFC 1918 - Private Use */
911+
*private = true;
912+
} else if (ip[0] == 198 && ip[1] >= 18 && ip[1] <= 19) {
913+
/* RFC 2544 - Benchmarking */
914+
} else if (ip[0] == 198 && ip[1] == 51 && ip[2] == 100) {
915+
/* RFC 5737 - Documentation */
916+
} else if (ip[0] == 203 && ip[1] == 0 && ip[2] == 113) {
917+
/* RFC 5737 - Documentation */
918+
} else if (ip[0] >= 240 && ip[1] <= 255) {
919+
/* RFC 1122 - Reserved */
920+
*reserved = true;
921+
} else if (ip[0] == 255 && ip[1] == 255 && ip[2] == 255 && ip[3] == 255) {
922+
/* RFC 0919 - Limited Broadcast, Updated by RFC 8190, 2.2. */
923+
*reserved = true;
924+
} else {
925+
return false;
926+
}
927+
928+
return true;
929+
}
930+
931+
/* From the tables in RFC 6890 - Special-Purpose IP Address Registries */
932+
static bool ipv6_get_status_flags(const int ip[8], bool *global, bool *reserved, bool *private)
873933
{
874-
/* validates an ipv4 or ipv6 IP, based on the flag (4, 6, or both) add a
875-
* flag to throw out reserved ranges; multicast ranges... etc. If both
876-
* allow_ipv4 and allow_ipv6 flags flag are used, then the first dot or
877-
* colon determine the format */
934+
*global = false;
935+
*reserved = false;
936+
*private = false;
937+
938+
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) {
939+
/* RFC 4291 - Unspecified Address */
940+
*reserved = true;
941+
} else if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 && ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && ip[7] == 1) {
942+
/* RFC 4291 - Loopback Address */
943+
*reserved = true;
944+
} else if (ip[0] == 0x0064 && ip[1] == 0xff9b) {
945+
/* RFC 6052 - IPv4-IPv6 Translation */
946+
*global = true;
947+
} else if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 && ip[4] == 0 && ip[5] == 0xffff) {
948+
/* RFC 4291 - IPv4-mapped Address */
949+
*reserved = true;
950+
} else if (ip[0] == 0x0100 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0) {
951+
/* RFC 6666 - Discard-Only Address Block */
952+
} else if (ip[0] == 0x2001 && ip[1] == 0x0000) {
953+
/* RFC 4380 - TEREDO */
954+
} else if (ip[0] == 0x2001 && ip[1] <= 0x01ff) {
955+
/* RFC 2928 - IETF Protocol Assignments */
956+
} else if (ip[0] == 0x2001 && ip[1] == 0x0002 && ip[2] == 0) {
957+
/* RFC 5180 - Benchmarking */
958+
} else if (ip[0] == 0x2001 && ip[1] == 0x0db8) {
959+
/* RFC 3849 - Documentation */
960+
} else if (ip[0] == 0x2001 && ip[1] >= 0x0010 && ip[1] <= 0x001f) {
961+
/* RFC 4843 - ORCHID */
962+
} else if (ip[0] == 0x2002) {
963+
/* RFC 3056 - 6to4 */
964+
} else if (ip[0] >= 0xfc00 && ip[0] <= 0xfdff) {
965+
/* RFC 4193 - Unique-Local */
966+
*private = true;
967+
} else if (ip[0] >= 0xfe80 && ip[0] <= 0xfebf) {
968+
/* RFC 4291 - Linked-Scoped Unicast */
969+
*reserved = true;
970+
} else {
971+
return false;
972+
}
878973

879-
int ip[8];
880-
int mode;
974+
return true;
975+
}
976+
977+
/* Validates an ipv4 or ipv6 IP, based on the flag (4, 6, or both) add a flag
978+
* to throw out reserved ranges; multicast ranges... etc. If both allow_ipv4
979+
* and allow_ipv6 flags flag are used, then the first dot or colon determine
980+
* the format */
981+
void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
982+
{
983+
int ip[8];
984+
int mode;
985+
bool flag_global, flag_reserved, flag_private; /* flags for ranges as determined by RFC 6890 */
881986

882987
if (memchr(Z_STRVAL_P(value), ':', Z_STRLEN_P(value))) {
883988
mode = FORMAT_IPV6;
@@ -895,86 +1000,35 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
8951000
RETURN_VALIDATION_FAILED
8961001
}
8971002

898-
switch (mode) {
899-
case FORMAT_IPV4:
900-
if (!_php_filter_validate_ipv4(Z_STRVAL_P(value), Z_STRLEN_P(value), ip)) {
901-
RETURN_VALIDATION_FAILED
902-
}
1003+
if (mode == FORMAT_IPV4) {
1004+
if (!_php_filter_validate_ipv4(Z_STRVAL_P(value), Z_STRLEN_P(value), ip)) {
1005+
RETURN_VALIDATION_FAILED
1006+
}
9031007

904-
/* Check flags */
905-
if (flags & FILTER_FLAG_NO_PRIV_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) {
906-
if (
907-
(ip[0] == 10) ||
908-
(ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) ||
909-
(ip[0] == 192 && ip[1] == 168)
910-
) {
911-
RETURN_VALIDATION_FAILED
912-
}
913-
}
1008+
if (!ipv4_get_status_flags(ip, &flag_global, &flag_reserved, &flag_private)) {
1009+
return; /* no special block */
1010+
}
1011+
}
1012+
else if (mode == FORMAT_IPV6) {
1013+
if (_php_filter_validate_ipv6(Z_STRVAL_P(value), Z_STRLEN_P(value), ip) < 1) {
1014+
RETURN_VALIDATION_FAILED
1015+
}
9141016

915-
if (flags & FILTER_FLAG_NO_RES_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) {
916-
if (
917-
(ip[0] == 0) ||
918-
(ip[0] >= 240) ||
919-
(ip[0] == 127) ||
920-
(ip[0] == 169 && ip[1] == 254)
921-
) {
922-
RETURN_VALIDATION_FAILED
923-
}
924-
}
1017+
if (!ipv6_get_status_flags(ip, &flag_global, &flag_reserved, &flag_private)) {
1018+
return; /* no special block */
1019+
}
1020+
}
9251021

926-
if (flags & FILTER_FLAG_GLOBAL_RANGE) {
927-
if (
928-
(ip[0] == 100 && ip[1] >= 64 && ip[1] <= 127 ) ||
929-
(ip[0] == 192 && ip[1] == 0 && ip[2] == 0 ) ||
930-
(ip[0] == 192 && ip[1] == 0 && ip[2] == 2 ) ||
931-
(ip[0] == 198 && ip[1] >= 18 && ip[1] <= 19 ) ||
932-
(ip[0] == 198 && ip[1] == 51 && ip[2] == 100 ) ||
933-
(ip[0] == 203 && ip[1] == 0 && ip[2] == 113 )
934-
) {
935-
RETURN_VALIDATION_FAILED
936-
}
937-
}
1022+
if ((flags & FILTER_FLAG_GLOBAL_RANGE) && flag_global != true) {
1023+
RETURN_VALIDATION_FAILED
1024+
}
9381025

939-
break;
1026+
if ((flags & FILTER_FLAG_NO_PRIV_RANGE) && flag_private == true) {
1027+
RETURN_VALIDATION_FAILED
1028+
}
9401029

941-
case FORMAT_IPV6:
942-
{
943-
int res = 0;
944-
res = _php_filter_validate_ipv6(Z_STRVAL_P(value), Z_STRLEN_P(value), ip);
945-
if (res < 1) {
946-
RETURN_VALIDATION_FAILED
947-
}
948-
/* Check flags */
949-
if (flags & FILTER_FLAG_NO_PRIV_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) {
950-
if (ip[0] >= 0xfc00 && ip[0] <= 0xfdff) {
951-
RETURN_VALIDATION_FAILED
952-
}
953-
}
954-
if (flags & FILTER_FLAG_NO_RES_RANGE || flags & FILTER_FLAG_GLOBAL_RANGE) {
955-
if (
956-
(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)) ||
957-
(ip[0] == 0x5f) ||
958-
(ip[0] >= 0xfe80 && ip[0] <= 0xfebf) ||
959-
(ip[0] == 0x2001 && (ip[1] == 0x0db8 || (ip[1] >= 0x0010 && ip[1] <= 0x001f))) ||
960-
(ip[0] == 0x3ff3)
961-
) {
962-
RETURN_VALIDATION_FAILED
963-
}
964-
}
965-
if (flags & FILTER_FLAG_GLOBAL_RANGE) {
966-
if (
967-
(ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 && ip[4] == 0 && ip[5] == 0xffff) ||
968-
(ip[0] == 0x0100 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0) ||
969-
(ip[0] == 0x2001 && ip[1] <= 0x01ff) ||
970-
(ip[0] == 0x2001 && ip[1] == 0x0002 && ip[2] == 0) ||
971-
(ip[0] >= 0xfc00 && ip[0] <= 0xfdff)
972-
) {
973-
RETURN_VALIDATION_FAILED
974-
}
975-
}
976-
}
977-
break;
1030+
if ((flags & FILTER_FLAG_NO_RES_RANGE) && flag_reserved == true) {
1031+
RETURN_VALIDATION_FAILED
9781032
}
9791033
}
9801034
/* }}} */

ext/filter/tests/PMOPB45.phpt renamed to ext/filter/tests/CVE-2007-1900.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
PMOPB-45-2007:PHP ext/filter Email Validation Vulnerability
2+
CVE-2007-1900: PHP ext/filter Email Validation Vulnerability
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/bug42718-2.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Bug #42718 - 2 (unsafe_raw filter not applied when configured as default filter)
2+
Bug #42718 (unsafe_raw filter not applied when configured as default filter)
33
--EXTENSIONS--
44
filter
55
--INI--

ext/filter/tests/bug47435.phpt

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ var_dump(filter_var("2001:0010::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
1818
var_dump(filter_var("2001:0010::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE));
1919
var_dump(filter_var("240b:0010::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
2020
var_dump(filter_var("240b:0010::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE));
21-
var_dump(filter_var("5f::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
22-
var_dump(filter_var("5f::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE));
23-
var_dump(filter_var("3ff3::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
24-
var_dump(filter_var("3ff3::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE));
2521
?>
2622
--EXPECT--
2723
string(7) "FC00::1"
@@ -33,12 +29,8 @@ bool(false)
3329
string(11) "fe80:5:6::1"
3430
bool(false)
3531
string(12) "2001:0db8::1"
36-
bool(false)
32+
string(12) "2001:0db8::1"
33+
string(12) "2001:0010::1"
3734
string(12) "2001:0010::1"
38-
bool(false)
3935
string(12) "240b:0010::1"
4036
string(12) "240b:0010::1"
41-
string(5) "5f::1"
42-
bool(false)
43-
string(7) "3ff3::1"
44-
bool(false)

ext/filter/tests/bug49274.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
#49274, fatal error when an object does not implement toString
2+
Bug #49274 (fatal error when an object does not implement toString)
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/bug49510.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Bug #49510 boolean validation fails with FILTER_NULL_ON_FAILURE
2+
Bug #49510 (boolean validation fails with FILTER_NULL_ON_FAILURE)
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/bug50632.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
bug 50632, filter_input() does not return default value if the variable does not exist
2+
Bug #50632 (filter_input() does not return default value if the variable does not exist)
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/bug51192.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
bug 51192, FILTER_VALIDATE_URL will invalidate a hostname that includes '-'
2+
Bug #51192 (FILTER_VALIDATE_URL will invalidate a hostname that includes '-')
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/bug51368.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
FR #51368 (php_filter_float does not allow custom thousand separators)
2+
Bug #51368 (php_filter_float does not allow custom thousand separators)
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/bug64441.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
bug 64441, FILTER_VALIDATE_URL will invalidate a hostname that ended by dot
2+
Bug #64441 (FILTER_VALIDATE_URL will invalidate a hostname that ended by dot)
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/bug67167.01.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Bug #67167: object with VALIDATE_BOOLEAN and NULL_ON_FAILURE
2+
Bug #67167 (object with VALIDATE_BOOLEAN and NULL_ON_FAILURE)
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/bug67167.02.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Bug #67167: filter_var(null,FILTER_VALIDATE_BOOLEAN,FILTER_NULL_ON_FAILURE) returns null
2+
Bug #67167 (filter_var(null,FILTER_VALIDATE_BOOLEAN,FILTER_NULL_ON_FAILURE) returns null)
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/bug7715.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
bug 7715, floats value with integer or incomplete input
2+
Bug #7715 (floats value with integer or incomplete input)
33
--INI--
44
precision=14
55
--EXTENSIONS--

ext/filter/tests/bug7733.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
filter_var() Float exponential weird result
2+
Bug #7733 (filter_var() Float exponential weird result)
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/bug80584.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Bug #80584: "0x" and "0X" are considered valid hex numbers by filter_var()
2+
Bug #80584 ("0x" and "0X" are considered valid hex numbers by filter_var())
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/bug8315.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
bug 8315, NULL values halt the validation
2+
Bug #8315 (NULL values halt the validation)
33
--EXTENSIONS--
44
filter
55
--FILE--

ext/filter/tests/gh16944.phpt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Bug GH-16944 (Invalid filtering of IPv6 with FILTER_FLAG_NO_RES_RANGE)
3+
--EXTENSIONS--
4+
filter
5+
--FILE--
6+
<?php
7+
var_dump(filter_var("::ffff:0:1", FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE));
8+
?>
9+
--EXPECT--
10+
bool(false)

0 commit comments

Comments
 (0)